Skip to content

Commit

Permalink
Add no-whitespace support
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron committed Jul 18, 2024
1 parent bdaa0bc commit 225f1a1
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 9 deletions.
178 changes: 169 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,33 +159,186 @@ where
word: &str,
tokens: &mut PeekableTokens<T>,
) -> Result<Self, &'static str> {
// Normally Z/M/ZM is separated by a space from the primary WKT word. E.g. `POINT Z`
// instead of `POINTZ`. However we wish to support both types (in reading). When written
// without a space, `POINTZ` is considered a single word, which means we need to include
// matches here.
match word {
w if w.eq_ignore_ascii_case("POINT") => {
let x = <Point<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x = <Point<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POINTZ") => {
let x = <Point<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POINTM") => {
let x = <Point<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POINTZM") => {
let x = <Point<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("LINESTRING") || w.eq_ignore_ascii_case("LINEARRING") => {
let x = <LineString<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x = <LineString<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("LINESTRINGZ") => {
let x = <LineString<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("LINESTRINGM") => {
let x = <LineString<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("LINESTRINGZM") => {
let x = <LineString<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POLYGON") => {
let x = <Polygon<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x = <Polygon<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POLYGONZ") => {
let x = <Polygon<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POLYGONM") => {
let x = <Polygon<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("POLYGONZM") => {
let x = <Polygon<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOINT") => {
let x = <MultiPoint<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x = <MultiPoint<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOINTZ") => {
let x = <MultiPoint<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOINTM") => {
let x = <MultiPoint<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOINTZM") => {
let x = <MultiPoint<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTILINESTRING") => {
let x = <MultiLineString<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x =
<MultiLineString<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTILINESTRINGZ") => {
let x = <MultiLineString<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTILINESTRINGM") => {
let x = <MultiLineString<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTILINESTRINGZM") => {
let x = <MultiLineString<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOLYGON") => {
let x = <MultiPolygon<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x = <MultiPolygon<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOLYGONZ") => {
let x = <MultiPolygon<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOLYGONM") => {
let x = <MultiPolygon<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("MULTIPOLYGONZM") => {
let x = <MultiPolygon<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("GEOMETRYCOLLECTION") => {
let x = <GeometryCollection<T> as FromTokens<T>>::from_tokens_with_header(tokens);
let x =
<GeometryCollection<T> as FromTokens<T>>::from_tokens_with_header(tokens, None);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("GEOMETRYCOLLECTIONZ") => {
let x = <GeometryCollection<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZ),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("GEOMETRYCOLLECTIONM") => {
let x = <GeometryCollection<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYM),
);
x.map(|y| y.into())
}
w if w.eq_ignore_ascii_case("GEOMETRYCOLLECTIONZM") => {
let x = <GeometryCollection<T> as FromTokens<T>>::from_tokens_with_header(
tokens,
Some(Dimension::XYZM),
);
x.map(|y| y.into())
}
_ => Err("Invalid type encountered"),
Expand Down Expand Up @@ -279,8 +432,15 @@ where

/// The preferred top-level FromTokens API, which additionally checks for the presence of Z, M,
/// and ZM in the token stream.
fn from_tokens_with_header(tokens: &mut PeekableTokens<T>) -> Result<Self, &'static str> {
let dim = infer_geom_dimension(tokens)?;
fn from_tokens_with_header(
tokens: &mut PeekableTokens<T>,
dim: Option<Dimension>,
) -> Result<Self, &'static str> {
let dim = if let Some(dim) = dim {
dim
} else {
infer_geom_dimension(tokens)?
};
FromTokens::from_tokens_with_parens(tokens, dim)
}

Expand Down
22 changes: 22 additions & 0 deletions src/types/linestring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,28 @@ mod tests {
assert_eq!(Some(5.0), coords[1].m);
}

#[test]
fn basic_linestring_zm_one_word() {
let wkt = Wkt::from_str("LINESTRINGZM (-117 33 2 3, -116 34 4 5)")
.ok()
.unwrap();
let coords = match wkt {
Wkt::LineString(LineString(coords)) => coords,
_ => unreachable!(),
};
assert_eq!(2, coords.len());

assert_eq!(-117.0, coords[0].x);
assert_eq!(33.0, coords[0].y);
assert_eq!(Some(2.0), coords[0].z);
assert_eq!(Some(3.0), coords[0].m);

assert_eq!(-116.0, coords[1].x);
assert_eq!(34.0, coords[1].y);
assert_eq!(Some(4.0), coords[1].z);
assert_eq!(Some(5.0), coords[1].m);
}

#[test]
fn write_empty_linestring() {
let linestring: LineString<f64> = LineString(vec![]);
Expand Down
13 changes: 13 additions & 0 deletions src/types/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ mod tests {
assert_eq!(None, coord.m);
}

#[test]
fn basic_point_z_one_word() {
let wkt = Wkt::from_str("POINTZ(-117 33 10)").ok().unwrap();
let coord = match wkt {
Wkt::Point(Point(Some(coord))) => coord,
_ => unreachable!(),
};
assert_eq!(-117.0, coord.x);
assert_eq!(33.0, coord.y);
assert_eq!(Some(10.0), coord.z);
assert_eq!(None, coord.m);
}

#[test]
fn basic_point_whitespace() {
let wkt: Wkt<f64> = Wkt::from_str(" \n\t\rPOINT \n\t\r( \n\r\t10 \n\t\r-20 \n\t\r) \n\t\r")
Expand Down

0 comments on commit 225f1a1

Please sign in to comment.