diff --git a/src/lib.rs b/src/lib.rs index 5a5132d..b6f3f67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,6 +168,35 @@ where let x = as FromTokens>::from_tokens_with_parens(tokens); x.map(|y| y.as_item()) } + w if w.eq_ignore_ascii_case("POINTZ") => { + let x = as FromTokens>::from_tokens_with_parens(tokens)?; + if let Some(coord) = &x.0 { + if coord.z.is_none() { + return Err("POINTZ must have a z-coordinate."); + } + } + Ok(x.as_item()) + } + w if w.eq_ignore_ascii_case("POINTM") => { + let mut x = as FromTokens>::from_tokens_with_parens(tokens)?; + if let Some(coord) = &mut x.0 { + if coord.z.is_none() { + return Err("POINTM must have an m-coordinate."); + } else { + coord.m = coord.z.take(); + } + } + Ok(x.as_item()) + } + w if w.eq_ignore_ascii_case("POINTZM") => { + let x = as FromTokens>::from_tokens_with_parens(tokens)?; + if let Some(coord) = &x.0 { + if coord.z.is_none() || coord.m.is_none() { + return Err("POINTZM must have both a z- and m-coordinate"); + } + } + Ok(x.as_item()) + } w if w.eq_ignore_ascii_case("LINESTRING") || w.eq_ignore_ascii_case("LINEARRING") => { let x = as FromTokens>::from_tokens_with_parens(tokens); x.map(|y| y.as_item()) @@ -360,6 +389,57 @@ mod tests { ); } + #[test] + fn test_points() { + // point(x, y) + let wkt = >::from_str("POINT (10 20.1)").ok().unwrap(); + match wkt.item { + Geometry::Point(Point(Some(coord))) => { + assert_eq!(coord.x, 10.0); + assert_eq!(coord.y, 20.1); + assert_eq!(coord.z, None); + assert_eq!(coord.m, None); + } + _ => panic!("excepted to be parsed as a POINT"), + } + + // point(x, y, z) + let wkt = >::from_str("POINTZ (10 20.1 5)").ok().unwrap(); + match wkt.item { + Geometry::Point(Point(Some(coord))) => { + assert_eq!(coord.x, 10.0); + assert_eq!(coord.y, 20.1); + assert_eq!(coord.z, Some(5.0)); + assert_eq!(coord.m, None); + } + _ => panic!("excepted to be parsed as a POINT"), + } + + // point(x, y, m) + let wkt = >::from_str("POINTM (10 20.1 80)").ok().unwrap(); + match wkt.item { + Geometry::Point(Point(Some(coord))) => { + assert_eq!(coord.x, 10.0); + assert_eq!(coord.y, 20.1); + assert_eq!(coord.z, None); + assert_eq!(coord.m, Some(80.0)); + } + _ => panic!("excepted to be parsed as a POINT"), + } + + // point(x, y, z, m) + let wkt = >::from_str("POINTZM (10 20.1 5 80)").ok().unwrap(); + match wkt.item { + Geometry::Point(Point(Some(coord))) => { + assert_eq!(coord.x, 10.0); + assert_eq!(coord.y, 20.1); + assert_eq!(coord.z, Some(5.0)); + assert_eq!(coord.m, Some(80.0)); + } + _ => panic!("excepted to be parsed as a POINT"), + } + } + #[test] fn support_jts_linearring() { let wkt: Wkt = Wkt::from_str("linearring (10 20, 30 40)").ok().unwrap(); diff --git a/src/types/coord.rs b/src/types/coord.rs index e740ed9..bb42c9e 100644 --- a/src/types/coord.rs +++ b/src/types/coord.rs @@ -57,12 +57,25 @@ where Some(Token::Number(n)) => n, _ => return Err("Expected a number for the Y coordinate"), }; - Ok(Coord { - x, - y, - z: None, - m: None, - }) + + let mut z = None; + let mut m = None; + + if let Some(Ok(Token::Number(_))) = tokens.peek() { + z = match tokens.next().transpose()? { + Some(Token::Number(n)) => Some(n), + _ => None, + }; + + if let Some(Ok(Token::Number(_))) = tokens.peek() { + m = match tokens.next().transpose()? { + Some(Token::Number(n)) => Some(n), + _ => None, + }; + } + } + + Ok(Coord { x, y, z, m }) } } diff --git a/src/types/point.rs b/src/types/point.rs index 3239637..66b3ebc 100644 --- a/src/types/point.rs +++ b/src/types/point.rs @@ -104,7 +104,6 @@ mod tests { >::from_str("POINT ()").err().unwrap(); >::from_str("POINT (10)").err().unwrap(); >::from_str("POINT 10").err().unwrap(); - >::from_str("POINT (10 -20 40)").err().unwrap(); } #[test]