From 04184b8deafd6c321f4ada9842c0ebd17374c736 Mon Sep 17 00:00:00 2001 From: "Simeon H.K. Fitch" Date: Fri, 19 Aug 2022 15:34:35 -0400 Subject: [PATCH 1/2] Added borrowed value conversion traits for geo_types. --- CHANGES.md | 2 + src/conversion/mod.rs | 16 ++++ src/conversion/to_geo_types.rs | 142 +++++++++++++++++++++++++++------ 3 files changed, 135 insertions(+), 25 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 16713e5..1f9cf5a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,8 @@ * * Add `geojson::Result` * +* Add `TryFrom<&geometry::Value>` for geo_type variants. + * <> ## 0.23.0 diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs index 4b2a08b..cf853d3 100644 --- a/src/conversion/mod.rs +++ b/src/conversion/mod.rs @@ -63,6 +63,22 @@ macro_rules! assert_almost_eq { }}; } + +macro_rules! try_from_owned_value { + ($to:ty) => { + #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] + impl TryFrom for $to + { + type Error = Error; + + fn try_from(value: geometry::Value) -> Result { + (&value).try_into() + } + } + }; +} + + pub(crate) mod from_geo_types; pub(crate) mod to_geo_types; diff --git a/src/conversion/to_geo_types.rs b/src/conversion/to_geo_types.rs index 8c72dc7..35d8727 100644 --- a/src/conversion/to_geo_types.rs +++ b/src/conversion/to_geo_types.rs @@ -10,28 +10,29 @@ use crate::{Error, Result}; use std::convert::{TryFrom, TryInto}; #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::Point +impl TryFrom<&geometry::Value> for geo_types::Point where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::Point(point_type) => Ok(create_geo_point(&point_type)), - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::Point); #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::MultiPoint +impl TryFrom<&geometry::Value> for geo_types::MultiPoint where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::MultiPoint(multi_point_type) => Ok(geo_types::MultiPoint( multi_point_type @@ -39,107 +40,116 @@ where .map(|point_type| create_geo_point(&point_type)) .collect(), )), - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::MultiPoint); #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::LineString +impl TryFrom<&geometry::Value> for geo_types::LineString where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::LineString(multi_point_type) => { Ok(create_geo_line_string(&multi_point_type)) } - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::LineString); #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::MultiLineString +impl TryFrom<&geometry::Value> for geo_types::MultiLineString where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::MultiLineString(multi_line_string_type) => { Ok(create_geo_multi_line_string(&multi_line_string_type)) } - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::MultiLineString); #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::Polygon +impl TryFrom<&geometry::Value> for geo_types::Polygon where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::Polygon(polygon_type) => Ok(create_geo_polygon(&polygon_type)), - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::Polygon); #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::MultiPolygon +impl TryFrom<&geometry::Value> for geo_types::MultiPolygon where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result> { + fn try_from(value: &geometry::Value) -> Result> { match value { geometry::Value::MultiPolygon(multi_polygon_type) => { Ok(create_geo_multi_polygon(&multi_polygon_type)) } - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::MultiPolygon); + #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::GeometryCollection +impl TryFrom<&geometry::Value> for geo_types::GeometryCollection where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::GeometryCollection(geometries) => { let geojson_geometries = geometries .iter() - .map(|geometry| geometry.value.clone().try_into().unwrap()) + .map(|geometry| (&geometry.value).try_into().unwrap()) .collect(); Ok(geo_types::GeometryCollection(geojson_geometries)) } - _ => Err(Error::InvalidGeometryConversion(value)), + _ => Err(Error::InvalidGeometryConversion(value.clone())), } } } +try_from_owned_value!(geo_types::GeometryCollection); + + #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] -impl TryFrom for geo_types::Geometry +impl TryFrom<&geometry::Value> for geo_types::Geometry where T: CoordFloat, { type Error = Error; - fn try_from(value: geometry::Value) -> Result { + fn try_from(value: &geometry::Value) -> Result { match value { geometry::Value::Point(ref point_type) => { Ok(geo_types::Geometry::Point(create_geo_point(point_type))) @@ -179,6 +189,7 @@ where } } } +try_from_owned_value!(geo_types::Geometry); #[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] impl TryFrom for geo_types::Geometry @@ -188,7 +199,19 @@ where type Error = Error; fn try_from(val: Geometry) -> Result> { - val.value.try_into() + (&val).try_into() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))] +impl TryFrom<&Geometry> for geo_types::Geometry +where + T: CoordFloat, +{ + type Error = Error; + + fn try_from(val: &Geometry) -> Result> { + (&val.value).try_into() } } @@ -620,4 +643,73 @@ mod tests { ])); assert_eq!(geo_geom, expected); } + + #[test] + fn borrowed_value_conversions_test() -> crate::Result<()> { + let coord1 = vec![100.0, 0.2]; + let coord2 = vec![101.0, 1.0]; + let coord3 = vec![102.0, 0.8]; + let coord4 = vec![104.0, 0.2]; + + let geojson_point = Value::Point(coord1.clone()); + let _: geo_types::Point = (&geojson_point).try_into()?; + + let geojson_multi_point = Value::MultiPoint(vec![coord1.clone(), coord2.clone()]); + let _: geo_types::MultiPoint = (&geojson_multi_point).try_into()?; + + let geojson_line_string = Value::LineString(vec![coord1.clone(), coord2.clone()]); + let _: geo_types::LineString = (&geojson_line_string).try_into()?; + + let geojson_multi_line_string = Value::MultiLineString(vec![ + vec![coord1.clone(), coord2.clone()], + vec![coord2.clone(), coord3.clone()], + ]); + let _: geo_types::MultiLineString = (&geojson_multi_line_string).try_into()?; + + let geojson_multi_line_string_type1 = vec![ + vec![ + coord1.clone(), + coord2.clone(), + coord3.clone(), + coord1.clone(), + ], + vec![ + coord4.clone(), + coord1.clone(), + coord2.clone(), + coord4.clone(), + ], + ]; + let geojson_polygon = Value::Polygon(geojson_multi_line_string_type1); + let _: geo_types::Polygon = (&geojson_polygon).try_into()?; + + let geojson_line_string_type1 = vec![ + coord1.clone(), + coord2.clone(), + coord3.clone(), + coord1.clone(), + ]; + + let geojson_line_string_type2 = vec![ + coord4.clone(), + coord3.clone(), + coord2.clone(), + coord4.clone(), + ]; + let geojson_multi_polygon = Value::MultiPolygon(vec![ + vec![geojson_line_string_type1], + vec![geojson_line_string_type2], + ]); + let _: geo_types::MultiPolygon = (&geojson_multi_polygon).try_into()?; + + let geojson_geometry_collection = Value::GeometryCollection(vec![ + Geometry::new(geojson_multi_point), + Geometry::new(geojson_multi_line_string), + Geometry::new(geojson_multi_polygon), + ]); + + let _: geo_types::GeometryCollection = (&geojson_geometry_collection).try_into()?; + + Ok(()) + } } From 39be51ee5cc5e7bfaff3853a7d7f42be3cc493e9 Mon Sep 17 00:00:00 2001 From: "Simeon H.K. Fitch" Date: Fri, 19 Aug 2022 15:42:18 -0400 Subject: [PATCH 2/2] Changelog update. --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1f9cf5a..57b53d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,7 +9,7 @@ * Add `geojson::Result` * * Add `TryFrom<&geometry::Value>` for geo_type variants. - * <> + * ## 0.23.0