Skip to content

Commit

Permalink
Work around geo_types to impl GeometryCollection::from_wkt_str
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelkirk committed Apr 28, 2022
1 parent ed53073 commit 9fecace
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 3 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
* New `FromWkt` trait allows a way to convert from a string or reader directly
to geo-types, without exposing you to the intermediate `Wkt` structs.
* <https://github.com/georust/wkt/pull/95>

* Implemented `geo_types::GeometryCollection::from(Wkt::from_str(wkt_str))`
* <https://github.com/georust/wkt/pull/95>

## 0.10.0 - 2022-02-24
### Changed
Expand Down
88 changes: 86 additions & 2 deletions src/geo_types_from_wkt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use crate::types::*;
use crate::{Geometry, TryFromWkt, Wkt, WktFloat};

use std::any::type_name;
use std::convert::{TryFrom, TryInto};
use std::io::Read;
use std::str::FromStr;
Expand Down Expand Up @@ -88,10 +89,54 @@ try_from_wkt_impl!(
MultiPoint,
MultiLineString,
MultiPolygon,
// See impl below.
// GeometryCollection,
Rect,
Triangle
);

/// Fallibly convert this WKT primitive into this [`geo_types`] primitive
impl<T: CoordFloat> TryFrom<Wkt<T>> for geo_types::GeometryCollection<T> {
type Error = Error;

fn try_from(wkt: Wkt<T>) -> Result<Self, Self::Error> {
match wkt.item {
Geometry::GeometryCollection(collection) => {
let geometries: Result<Vec<geo_types::Geometry<T>>, _> =
collection.0.into_iter().map(TryFrom::try_from).collect();
Ok(geo_types::GeometryCollection(geometries?))
}
// geo_types doesn't implement `Geometry::try_from(geom_collec)` yet
// (see https://github.com/georust/geo/pull/821).
// So instead we synthesize the type of error it *would* return.
Geometry::Point(_) => Err(Error::MismatchedGeometry {
expected: type_name::<Self>(),
found: type_name::<geo_types::Point<T>>(),
}),
Geometry::LineString(_) => Err(Error::MismatchedGeometry {
expected: type_name::<Self>(),
found: type_name::<geo_types::LineString<T>>(),
}),
Geometry::Polygon(_) => Err(Error::MismatchedGeometry {
expected: type_name::<Self>(),
found: type_name::<geo_types::Polygon<T>>(),
}),
Geometry::MultiPoint(_) => Err(Error::MismatchedGeometry {
expected: type_name::<Self>(),
found: type_name::<geo_types::MultiPoint<T>>(),
}),
Geometry::MultiLineString(_) => Err(Error::MismatchedGeometry {
expected: type_name::<Self>(),
found: type_name::<geo_types::MultiLineString<T>>(),
}),
Geometry::MultiPolygon(_) => Err(Error::MismatchedGeometry {
expected: type_name::<Self>(),
found: type_name::<geo_types::MultiPolygon<T>>(),
}),
}
}
}

impl<T> From<Coord<T>> for geo_types::Coordinate<T>
where
T: CoordFloat,
Expand Down Expand Up @@ -335,7 +380,6 @@ macro_rules! try_from_wkt_impl {
}
}

// FIXME: What about GeometryCollection?
try_from_wkt_impl![
geo_types::Geometry<T>,
geo_types::Point<T>,
Expand All @@ -345,6 +389,7 @@ try_from_wkt_impl![
geo_types::MultiPoint<T>,
geo_types::MultiLineString<T>,
geo_types::MultiPolygon<T>,
geo_types::GeometryCollection<T>,
geo_types::Triangle<T>,
geo_types::Rect<T>,
];
Expand Down Expand Up @@ -921,6 +966,42 @@ mod tests {
);
}

#[test]
fn geom_collection_from_wkt_str() {
// geometry collections have some special handling vs. other geometries, so we test them separately.
let collection = geo_types::GeometryCollection::<f64>::try_from_wkt_str(
"GeometryCollection(POINT(1 2))",
)
.unwrap();
let point: geo_types::Point<_> = collection[0].clone().try_into().unwrap();
assert_eq!(point.y(), 2.0);
}

#[test]
fn geom_collection_from_invalid_wkt_str() {
// geometry collections have some special handling vs. other geometries, so we test them separately.
let err = geo_types::GeometryCollection::<f64>::try_from_wkt_str("GeomColl(POINT(1 2))")
.unwrap_err();
match err {
Error::InvalidWKT(err_text) => assert_eq!(err_text, "Invalid type encountered"),
e => panic!("Not the error we expected. Found: {}", e),
}
}

#[test]
fn geom_collection_from_other_wkt_str() {
// geometry collections have some special handling vs. other geometries, so we test them separately.
let not_a_collection = geo_types::GeometryCollection::<f64>::try_from_wkt_str("POINT(1 2)");
let err = not_a_collection.unwrap_err();
match err {
Error::MismatchedGeometry {
expected: "geo_types::geometry_collection::GeometryCollection<f64>",
found: "geo_types::point::Point<f64>",
} => {}
e => panic!("Not the error we expected. Found: {}", e),
}
}

#[test]
fn from_invalid_wkt_str() {
let a_point_too_many = geo_types::Point::<f64>::try_from_wkt_str("PINT(1 2)");
Expand All @@ -937,7 +1018,10 @@ mod tests {
geo_types::LineString::<f64>::try_from_wkt_str("POINT(1 2)");
let err = not_actually_a_line_string.unwrap_err();
match err {
Error::MismatchedGeometry { .. } => {}
Error::MismatchedGeometry {
expected: "geo_types::line_string::LineString<f64>",
found: "geo_types::point::Point<f64>",
} => {}
e => panic!("Not the error we expected. Found: {}", e),
}
}
Expand Down

0 comments on commit 9fecace

Please sign in to comment.