From 87e501d1e57b87e2055aa3d6d1c97559e4fd85cf Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 15 Sep 2023 12:53:28 -0700 Subject: [PATCH] Replace Wkt with its inner Geometry. This is a large breaking change to simplify the Wkt data structure. Wkt had a single field - `item` of type `Geometry`. So everything about a Wkt was determined by its item. In effect, Wkt was serving no purpose. So I replaced Wkt with it's inner Geometry. --- CHANGES.md | 2 + src/deserialize/geo_types.rs | 5 +- src/deserialize/mod.rs | 30 +++------ src/geo_types_from_wkt.rs | 115 ++++++++++++++------------------ src/geo_types_to_wkt.rs | 68 ++++++------------- src/lib.rs | 103 ++++++++++++---------------- src/types/geometrycollection.rs | 36 +++++----- src/types/linestring.rs | 14 ++-- src/types/multilinestring.rs | 14 ++-- src/types/multipoint.rs | 26 ++++---- src/types/multipolygon.rs | 14 ++-- src/types/point.rs | 18 ++--- src/types/polygon.rs | 14 ++-- 13 files changed, 193 insertions(+), 266 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dacffce..60cf3e8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,8 @@ * Bump min version of geo-types, and update geo_types::Coordinate to non-deprecated geo_types::Coord * BREAKING: WktNum must implement PartialEq * Implement PartialEq for Wkt +* BREAKING: Simplify Wkt data structure by replacing it with it's only field (formerly known as `item: Geometry`) +* BREAKING: Replace geometry_variant.as_item() with Wkt::from(geometry_variant) ## 0.10.3 - 2022-06-22 diff --git a/src/deserialize/geo_types.rs b/src/deserialize/geo_types.rs index b83b8e6..649235e 100644 --- a/src/deserialize/geo_types.rs +++ b/src/deserialize/geo_types.rs @@ -1,4 +1,4 @@ -use crate::{Geometry, Wkt, WktNum}; +use crate::{Wkt, WktNum}; use serde::de::{Deserialize, Deserializer, Error}; use std::{default::Default, str::FromStr}; @@ -9,8 +9,7 @@ where D: Deserializer<'de>, T: FromStr + Default + WktNum, { - Geometry::deserialize(deserializer) - .and_then(|g: Geometry| g.try_into().map_err(D::Error::custom)) + Wkt::deserialize(deserializer).and_then(|g: Wkt| g.try_into().map_err(D::Error::custom)) } /// Deserializes from WKT format into an `Option`. diff --git a/src/deserialize/mod.rs b/src/deserialize/mod.rs index 0aad8d4..3f91a20 100644 --- a/src/deserialize/mod.rs +++ b/src/deserialize/mod.rs @@ -1,10 +1,10 @@ //! This module deserialises to WKT using [`serde`]. //! //! You can deserialise to [`geo_types`] or any other implementor of [`TryFromWkt`], using -//! [`deserialize_wkt`]. Or you can store this crates internal primitives [`Wkt`] -//! or [`Geometry`] in your struct fields. +//! [`deserialize_wkt`]. Or you can store this crates internal primitives [`wkt`] +//! or [`Wkt`] in your struct fields. -use crate::{Geometry, TryFromWkt, Wkt, WktNum}; +use crate::{TryFromWkt, Wkt, WktNum}; use serde::de::{Deserializer, Error, Visitor}; use std::{ default::Default, @@ -160,7 +160,7 @@ impl<'de, T> Visitor<'de> for GeometryVisitor where T: FromStr + Default + WktNum, { - type Value = Geometry; + type Value = Wkt; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { write!(formatter, "a valid WKT format") } @@ -169,19 +169,7 @@ where E: Error, { let wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?; - Ok(wkt.item) - } -} - -impl<'de, T> serde::Deserialize<'de> for Geometry -where - T: FromStr + Default + WktNum, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(GeometryVisitor::default()) + Ok(wkt) } } @@ -190,7 +178,7 @@ mod tests { use super::*; use crate::{ types::{Coord, Point}, - Geometry, + Wkt, }; use serde::de::{ value::{Error, StrDeserializer}, @@ -207,8 +195,8 @@ mod tests { .deserialize_any(WktVisitor::::default()) .unwrap(); assert!(matches!( - wkt.item, - Geometry::Point(Point(Some(Coord { + wkt, + Wkt::Point(Point(Some(Coord { x: _, // floating-point types cannot be used in patterns y: _, // floating-point types cannot be used in patterns z: None, @@ -239,7 +227,7 @@ mod tests { .unwrap(); assert!(matches!( geometry, - Geometry::Point(Point(Some(Coord { + Wkt::Point(Point(Some(Coord { x: _, // floating-point types cannot be used in patterns y: _, // floating-point types cannot be used in patterns z: None, diff --git a/src/geo_types_from_wkt.rs b/src/geo_types_from_wkt.rs index eb3af4b..b89cf32 100644 --- a/src/geo_types_from_wkt.rs +++ b/src/geo_types_from_wkt.rs @@ -16,7 +16,7 @@ // limitations under the License. use crate::types::*; -use crate::{Geometry, TryFromWkt, Wkt}; +use crate::{TryFromWkt, Wkt}; use std::any::type_name; use std::convert::{TryFrom, TryInto}; @@ -44,17 +44,6 @@ pub enum Error { External(Box), } -impl TryFrom> for geo_types::Geometry -where - T: CoordNum, -{ - type Error = Error; - /// Try to convert from a WKT member to a [`geo-types`] primitive or collection - fn try_from(wkt: Wkt) -> Result { - Self::try_from(wkt.item) - } -} - macro_rules! try_from_wkt_impl { ($($type: ident),+) => { $( @@ -63,8 +52,7 @@ macro_rules! try_from_wkt_impl { type Error = Error; fn try_from(wkt: Wkt) -> Result { - let item = wkt.item; - let geometry = geo_types::Geometry::try_from(item)?; + let geometry = geo_types::Geometry::try_from(wkt)?; Self::try_from(geometry).map_err(|e| { match e { geo_types::Error::MismatchedGeometry { expected, found } => { @@ -100,8 +88,8 @@ impl TryFrom> for geo_types::GeometryCollection { type Error = Error; fn try_from(wkt: Wkt) -> Result { - match wkt.item { - Geometry::GeometryCollection(collection) => { + match wkt { + Wkt::GeometryCollection(collection) => { let geometries: Result>, _> = collection.0.into_iter().map(TryFrom::try_from).collect(); Ok(geo_types::GeometryCollection(geometries?)) @@ -109,27 +97,27 @@ impl TryFrom> for geo_types::GeometryCollection { // 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 { + Wkt::Point(_) => Err(Error::MismatchedGeometry { expected: type_name::(), found: type_name::>(), }), - Geometry::LineString(_) => Err(Error::MismatchedGeometry { + Wkt::LineString(_) => Err(Error::MismatchedGeometry { expected: type_name::(), found: type_name::>(), }), - Geometry::Polygon(_) => Err(Error::MismatchedGeometry { + Wkt::Polygon(_) => Err(Error::MismatchedGeometry { expected: type_name::(), found: type_name::>(), }), - Geometry::MultiPoint(_) => Err(Error::MismatchedGeometry { + Wkt::MultiPoint(_) => Err(Error::MismatchedGeometry { expected: type_name::(), found: type_name::>(), }), - Geometry::MultiLineString(_) => Err(Error::MismatchedGeometry { + Wkt::MultiLineString(_) => Err(Error::MismatchedGeometry { expected: type_name::(), found: type_name::>(), }), - Geometry::MultiPolygon(_) => Err(Error::MismatchedGeometry { + Wkt::MultiPolygon(_) => Err(Error::MismatchedGeometry { expected: type_name::(), found: type_name::>(), }), @@ -163,7 +151,7 @@ where } #[deprecated(since = "0.9.0", note = "use `geometry.try_into()` instead")] -pub fn try_into_geometry(geometry: &Geometry) -> Result, Error> +pub fn try_into_geometry(geometry: &Wkt) -> Result, Error> where T: CoordNum, { @@ -318,22 +306,22 @@ where let geo_geometries = geometry_collection .0 .into_iter() - .map(Geometry::try_into) + .map(Wkt::try_into) .collect::>()?; Ok(geo_types::GeometryCollection(geo_geometries)) } } -impl TryFrom> for geo_types::Geometry +impl TryFrom> for geo_types::Geometry where T: CoordNum, { type Error = Error; - fn try_from(geometry: Geometry) -> Result { + fn try_from(geometry: Wkt) -> Result { Ok(match geometry { - Geometry::Point(g) => { + Wkt::Point(g) => { // Special case as `geo::Point` can't be empty if g.0.is_some() { geo_types::Point::try_from(g)?.into() @@ -341,14 +329,12 @@ where geo_types::MultiPoint(vec![]).into() } } - Geometry::LineString(g) => geo_types::Geometry::LineString(g.into()), - Geometry::Polygon(g) => geo_types::Geometry::Polygon(g.into()), - Geometry::MultiLineString(g) => geo_types::Geometry::MultiLineString(g.into()), - Geometry::MultiPoint(g) => geo_types::Geometry::MultiPoint(g.try_into()?), - Geometry::MultiPolygon(g) => geo_types::Geometry::MultiPolygon(g.into()), - Geometry::GeometryCollection(g) => { - geo_types::Geometry::GeometryCollection(g.try_into()?) - } + Wkt::LineString(g) => geo_types::Geometry::LineString(g.into()), + Wkt::Polygon(g) => geo_types::Geometry::Polygon(g.into()), + Wkt::MultiLineString(g) => geo_types::Geometry::MultiLineString(g.into()), + Wkt::MultiPoint(g) => geo_types::Geometry::MultiPoint(g.try_into()?), + Wkt::MultiPolygon(g) => geo_types::Geometry::MultiPolygon(g.into()), + Wkt::GeometryCollection(g) => geo_types::Geometry::GeometryCollection(g.try_into()?), }) } } @@ -400,14 +386,12 @@ mod tests { #[test] fn convert_single_item_wkt() { - let w_point = Point(Some(Coord { + let wkt = Wkt::from(Point(Some(Coord { x: 1.0, y: 2.0, z: None, m: None, - })) - .as_item(); - let wkt = Wkt { item: w_point }; + }))); let converted = geo_types::Geometry::try_from(wkt).unwrap(); let g_point: geo_types::Point = geo_types::Point::new(1.0, 2.0); @@ -424,13 +408,12 @@ mod tests { #[test] fn convert_point() { - let point = Point(Some(Coord { + let point = Wkt::from(Point(Some(Coord { x: 10., y: 20., z: None, m: None, - })) - .as_item(); + }))); let g_point: geo_types::Point = (10., 20.).into(); assert_eq!( @@ -441,7 +424,7 @@ mod tests { #[test] fn convert_empty_linestring() { - let w_linestring = LineString(vec![]).as_item(); + let w_linestring = Wkt::from(LineString(vec![])); let g_linestring: geo_types::LineString = geo_types::LineString(vec![]); assert_eq!( geo_types::Geometry::LineString(g_linestring), @@ -451,7 +434,7 @@ mod tests { #[test] fn convert_linestring() { - let w_linestring = LineString(vec![ + let w_linestring: Wkt = LineString(vec![ Coord { x: 10., y: 20., @@ -465,7 +448,7 @@ mod tests { m: None, }, ]) - .as_item(); + .into(); let g_linestring: geo_types::LineString = vec![(10., 20.), (30., 40.)].into(); assert_eq!( geo_types::Geometry::LineString(g_linestring), @@ -475,7 +458,7 @@ mod tests { #[test] fn convert_empty_polygon() { - let w_polygon = Polygon(vec![]).as_item(); + let w_polygon: Wkt = Polygon(vec![]).into(); let g_polygon: geo_types::Polygon = geo_types::Polygon::new(geo_types::LineString(vec![]), vec![]); assert_eq!( @@ -486,7 +469,7 @@ mod tests { #[test] fn convert_polygon() { - let w_polygon = Polygon(vec![ + let w_polygon: Wkt = Polygon(vec![ LineString(vec![ Coord { x: 0., @@ -540,7 +523,7 @@ mod tests { }, ]), ]) - .as_item(); + .into(); let g_polygon: geo_types::Polygon = geo_types::Polygon::new( vec![(0., 0.), (20., 40.), (40., 0.), (0., 0.)].into(), vec![vec![(5., 5.), (20., 30.), (30., 5.), (5., 5.)].into()], @@ -553,7 +536,7 @@ mod tests { #[test] fn convert_empty_multilinestring() { - let w_multilinestring = MultiLineString(vec![]).as_item(); + let w_multilinestring: Wkt = MultiLineString(vec![]).into(); let g_multilinestring: geo_types::MultiLineString = geo_types::MultiLineString(vec![]); assert_eq!( geo_types::Geometry::MultiLineString(g_multilinestring), @@ -563,7 +546,7 @@ mod tests { #[test] fn convert_multilinestring() { - let w_multilinestring = MultiLineString(vec![ + let w_multilinestring: Wkt = MultiLineString(vec![ LineString(vec![ Coord { x: 10., @@ -593,7 +576,7 @@ mod tests { }, ]), ]) - .as_item(); + .into(); let g_multilinestring: geo_types::MultiLineString = geo_types::MultiLineString(vec![ vec![(10., 20.), (30., 40.)].into(), vec![(50., 60.), (70., 80.)].into(), @@ -606,7 +589,7 @@ mod tests { #[test] fn convert_empty_multipoint() { - let w_multipoint = MultiPoint(vec![]).as_item(); + let w_multipoint: Wkt = MultiPoint(vec![]).into(); let g_multipoint: geo_types::MultiPoint = geo_types::MultiPoint(vec![]); assert_eq!( geo_types::Geometry::MultiPoint(g_multipoint), @@ -616,7 +599,7 @@ mod tests { #[test] fn convert_multipoint() { - let w_multipoint = MultiPoint(vec![ + let w_multipoint: Wkt = MultiPoint(vec![ Point(Some(Coord { x: 10., y: 20., @@ -630,7 +613,7 @@ mod tests { m: None, })), ]) - .as_item(); + .into(); let g_multipoint: geo_types::MultiPoint = vec![(10., 20.), (30., 40.)].into(); assert_eq!( geo_types::Geometry::MultiPoint(g_multipoint), @@ -640,7 +623,7 @@ mod tests { #[test] fn convert_empty_multipolygon() { - let w_multipolygon = MultiPolygon(vec![]).as_item(); + let w_multipolygon: Wkt = MultiPolygon(vec![]).into(); let g_multipolygon: geo_types::MultiPolygon = geo_types::MultiPolygon(vec![]); assert_eq!( geo_types::Geometry::MultiPolygon(g_multipolygon), @@ -650,7 +633,7 @@ mod tests { #[test] fn convert_multipolygon() { - let w_multipolygon = MultiPolygon(vec![ + let w_multipolygon: Wkt = MultiPolygon(vec![ Polygon(vec![ LineString(vec![ Coord { @@ -732,7 +715,7 @@ mod tests { }, ])]), ]) - .as_item(); + .into(); let g_multipolygon: geo_types::MultiPolygon = geo_types::MultiPolygon(vec![ geo_types::Polygon::new( @@ -752,7 +735,7 @@ mod tests { #[test] fn convert_empty_geometrycollection() { - let w_geometrycollection = GeometryCollection(vec![]).as_item(); + let w_geometrycollection: Wkt = GeometryCollection(vec![]).into(); let g_geometrycollection: geo_types::GeometryCollection = geo_types::GeometryCollection(vec![]); assert_eq!( @@ -769,7 +752,7 @@ mod tests { z: None, m: None, })) - .as_item(); + .into(); let w_linestring = LineString(vec![ Coord { @@ -785,7 +768,7 @@ mod tests { m: None, }, ]) - .as_item(); + .into(); let w_polygon = Polygon(vec![LineString(vec![ Coord { @@ -813,7 +796,7 @@ mod tests { m: None, }, ])]) - .as_item(); + .into(); let w_multilinestring = MultiLineString(vec![ LineString(vec![ @@ -845,7 +828,7 @@ mod tests { }, ]), ]) - .as_item(); + .into(); let w_multipoint = MultiPoint(vec![ Point(Some(Coord { @@ -861,7 +844,7 @@ mod tests { m: None, })), ]) - .as_item(); + .into(); let w_multipolygon = MultiPolygon(vec![ Polygon(vec![LineString(vec![ @@ -917,9 +900,9 @@ mod tests { }, ])]), ]) - .as_item(); + .into(); - let w_geometrycollection = GeometryCollection(vec![ + let w_geometrycollection: Wkt = GeometryCollection(vec![ w_point, w_multipoint, w_linestring, @@ -927,7 +910,7 @@ mod tests { w_polygon, w_multipolygon, ]) - .as_item(); + .into(); let g_point: geo_types::Point = (10., 20.).into(); let g_linestring: geo_types::LineString = vec![(10., 20.), (30., 40.)].into(); diff --git a/src/geo_types_to_wkt.rs b/src/geo_types_to_wkt.rs index 76f94a0..e664ae3 100644 --- a/src/geo_types_to_wkt.rs +++ b/src/geo_types_to_wkt.rs @@ -4,7 +4,7 @@ use crate::types::{ Coord, GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, }; -use crate::{Geometry, ToWkt, Wkt}; +use crate::{ToWkt, Wkt}; /// # Examples /// ``` @@ -49,9 +49,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_point_to_w_point(self).as_item(), - } + Wkt::Point(g_point_to_w_point(self)) } } @@ -69,9 +67,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_line_to_w_linestring(self).as_item(), - } + g_line_to_w_linestring(self).into() } } @@ -89,9 +85,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_linestring_to_w_linestring(self).as_item(), - } + g_linestring_to_w_linestring(self).into() } } @@ -109,9 +103,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_polygon_to_w_polygon(self).as_item(), - } + g_polygon_to_w_polygon(self).into() } } @@ -129,9 +121,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_mpoint_to_w_mpoint(self).as_item(), - } + g_mpoint_to_w_mpoint(self).into() } } @@ -151,9 +141,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_mline_to_w_mline(self).as_item(), - } + g_mline_to_w_mline(self).into() } } @@ -175,9 +163,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_mpolygon_to_w_mpolygon(self).as_item(), - } + g_mpolygon_to_w_mpolygon(self).into() } } @@ -197,9 +183,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_geocol_to_w_geocol(self).as_item(), - } + g_geocol_to_w_geocol(self).into() } } @@ -217,9 +201,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_rect_to_w_polygon(self).as_item(), - } + g_rect_to_w_polygon(self).into() } } @@ -237,9 +219,7 @@ where T: CoordNum + std::fmt::Display, { fn to_wkt(&self) -> Wkt { - Wkt { - item: g_triangle_to_w_polygon(self).as_item(), - } + g_triangle_to_w_polygon(self).into() } } @@ -405,37 +385,33 @@ where GeometryCollection(w_geoms) } -fn g_geom_to_w_geom(g_geom: &geo_types::Geometry) -> Geometry +fn g_geom_to_w_geom(g_geom: &geo_types::Geometry) -> Wkt where T: CoordNum, { match *g_geom { - geo_types::Geometry::Point(ref g_point) => g_point_to_w_point(g_point).as_item(), + geo_types::Geometry::Point(ref g_point) => g_point_to_w_point(g_point).into(), - geo_types::Geometry::Line(ref g_line) => g_line_to_w_linestring(g_line).as_item(), + geo_types::Geometry::Line(ref g_line) => g_line_to_w_linestring(g_line).into(), - geo_types::Geometry::LineString(ref g_line) => { - g_linestring_to_w_linestring(g_line).as_item() - } + geo_types::Geometry::LineString(ref g_line) => g_linestring_to_w_linestring(g_line).into(), - geo_types::Geometry::Triangle(ref g_triangle) => { - g_triangle_to_w_polygon(g_triangle).as_item() - } + geo_types::Geometry::Triangle(ref g_triangle) => g_triangle_to_w_polygon(g_triangle).into(), - geo_types::Geometry::Rect(ref g_rect) => g_rect_to_w_polygon(g_rect).as_item(), + geo_types::Geometry::Rect(ref g_rect) => g_rect_to_w_polygon(g_rect).into(), - geo_types::Geometry::Polygon(ref g_polygon) => g_polygon_to_w_polygon(g_polygon).as_item(), + geo_types::Geometry::Polygon(ref g_polygon) => g_polygon_to_w_polygon(g_polygon).into(), - geo_types::Geometry::MultiPoint(ref g_mpoint) => g_mpoint_to_w_mpoint(g_mpoint).as_item(), + geo_types::Geometry::MultiPoint(ref g_mpoint) => g_mpoint_to_w_mpoint(g_mpoint).into(), - geo_types::Geometry::MultiLineString(ref g_mline) => g_mline_to_w_mline(g_mline).as_item(), + geo_types::Geometry::MultiLineString(ref g_mline) => g_mline_to_w_mline(g_mline).into(), geo_types::Geometry::MultiPolygon(ref g_mpolygon) => { - g_mpolygon_to_w_mpolygon(g_mpolygon).as_item() + g_mpolygon_to_w_mpolygon(g_mpolygon).into() } geo_types::Geometry::GeometryCollection(ref g_geocol) => { - g_geocol_to_w_geocol(g_geocol).as_item() + g_geocol_to_w_geocol(g_geocol).into() } } } diff --git a/src/lib.rs b/src/lib.rs index b6f3f67..3cb3f8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,11 +67,10 @@ //! ``` //! use std::str::FromStr; //! use wkt::Wkt; -//! use wkt::Geometry; //! //! let wktls: Wkt = Wkt::from_str("LINESTRING(10 20, 20 30)").unwrap(); -//! let ls = match wktls.item { -//! Geometry::LineString(line_string) => { +//! let ls = match wktls { +//! Wkt::LineString(line_string) => { //! // you now have access to the `wkt::types::LineString`. //! assert_eq!(line_string.0[0].x, 10.0); //! } @@ -142,7 +141,7 @@ impl WktFloat for T where T: WktNum + Float {} #[derive(Clone, Debug, PartialEq)] /// All supported WKT geometry [`types`] -pub enum Geometry +pub enum Wkt where T: WktNum, { @@ -155,7 +154,7 @@ where GeometryCollection(GeometryCollection), } -impl Geometry +impl Wkt where T: WktNum + FromStr + Default, { @@ -166,7 +165,7 @@ where match word { w if w.eq_ignore_ascii_case("POINT") => { let x = as FromTokens>::from_tokens_with_parens(tokens); - x.map(|y| y.as_item()) + x.map(|y| y.into()) } w if w.eq_ignore_ascii_case("POINTZ") => { let x = as FromTokens>::from_tokens_with_parens(tokens)?; @@ -175,7 +174,7 @@ where return Err("POINTZ must have a z-coordinate."); } } - Ok(x.as_item()) + Ok(x.into()) } w if w.eq_ignore_ascii_case("POINTM") => { let mut x = as FromTokens>::from_tokens_with_parens(tokens)?; @@ -186,7 +185,7 @@ where coord.m = coord.z.take(); } } - Ok(x.as_item()) + Ok(x.into()) } w if w.eq_ignore_ascii_case("POINTZM") => { let x = as FromTokens>::from_tokens_with_parens(tokens)?; @@ -195,65 +194,54 @@ where return Err("POINTZM must have both a z- and m-coordinate"); } } - Ok(x.as_item()) + Ok(x.into()) } 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()) + x.map(|y| y.into()) } w if w.eq_ignore_ascii_case("POLYGON") => { let x = as FromTokens>::from_tokens_with_parens(tokens); - x.map(|y| y.as_item()) + x.map(|y| y.into()) } w if w.eq_ignore_ascii_case("MULTIPOINT") => { let x = as FromTokens>::from_tokens_with_parens(tokens); - x.map(|y| y.as_item()) + x.map(|y| y.into()) } w if w.eq_ignore_ascii_case("MULTILINESTRING") => { let x = as FromTokens>::from_tokens_with_parens(tokens); - x.map(|y| y.as_item()) + x.map(|y| y.into()) } w if w.eq_ignore_ascii_case("MULTIPOLYGON") => { let x = as FromTokens>::from_tokens_with_parens(tokens); - x.map(|y| y.as_item()) + x.map(|y| y.into()) } w if w.eq_ignore_ascii_case("GEOMETRYCOLLECTION") => { let x = as FromTokens>::from_tokens_with_parens(tokens); - x.map(|y| y.as_item()) + x.map(|y| y.into()) } _ => Err("Invalid type encountered"), } } } -impl fmt::Display for Geometry +impl fmt::Display for Wkt where T: WktNum + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - Geometry::Point(point) => point.fmt(f), - Geometry::LineString(linestring) => linestring.fmt(f), - Geometry::Polygon(polygon) => polygon.fmt(f), - Geometry::MultiPoint(multipoint) => multipoint.fmt(f), - Geometry::MultiLineString(multilinstring) => multilinstring.fmt(f), - Geometry::MultiPolygon(multipolygon) => multipolygon.fmt(f), - Geometry::GeometryCollection(geometrycollection) => geometrycollection.fmt(f), + Wkt::Point(point) => point.fmt(f), + Wkt::LineString(linestring) => linestring.fmt(f), + Wkt::Polygon(polygon) => polygon.fmt(f), + Wkt::MultiPoint(multipoint) => multipoint.fmt(f), + Wkt::MultiLineString(multilinstring) => multilinstring.fmt(f), + Wkt::MultiPolygon(multipolygon) => multipolygon.fmt(f), + Wkt::GeometryCollection(geometrycollection) => geometrycollection.fmt(f), } } } -#[derive(Clone, Debug)] -/// Container for WKT primitives and collections -/// -/// This type can be fallibly converted to a [`geo_types`] primitive using [`std::convert::TryFrom`]. -pub struct Wkt -where - T: WktNum, -{ - pub item: Geometry, -} - impl Wkt where T: WktNum + FromStr + Default, @@ -269,7 +257,7 @@ where } _ => return Err("Invalid WKT format"), }; - Geometry::from_word_and_tokens(&word, &mut tokens).map(|item| Wkt { item }) + Wkt::from_word_and_tokens(&word, &mut tokens) } } @@ -284,15 +272,6 @@ where } } -impl fmt::Display for Wkt -where - T: WktNum + fmt::Debug + fmt::Display, -{ - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.item.fmt(formatter) - } -} - trait FromTokens: Sized + Default where T: WktNum + FromStr + Default, @@ -347,7 +326,7 @@ where #[cfg(test)] mod tests { use crate::types::{Coord, MultiPolygon, Point}; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] @@ -359,14 +338,14 @@ mod tests { #[test] fn empty_items() { let wkt: Wkt = Wkt::from_str("POINT EMPTY").ok().unwrap(); - match wkt.item { - Geometry::Point(Point(None)) => (), + match wkt { + Wkt::Point(Point(None)) => (), _ => unreachable!(), }; let wkt: Wkt = Wkt::from_str("MULTIPOLYGON EMPTY").ok().unwrap(); - match wkt.item { - Geometry::MultiPolygon(MultiPolygon(polygons)) => assert_eq!(polygons.len(), 0), + match wkt { + Wkt::MultiPolygon(MultiPolygon(polygons)) => assert_eq!(polygons.len(), 0), _ => unreachable!(), }; } @@ -374,8 +353,8 @@ mod tests { #[test] fn lowercase_point() { let wkt: Wkt = Wkt::from_str("point EMPTY").ok().unwrap(); - match wkt.item { - Geometry::Point(Point(None)) => (), + match wkt { + Wkt::Point(Point(None)) => (), _ => unreachable!(), }; } @@ -393,8 +372,8 @@ mod tests { fn test_points() { // point(x, y) let wkt = >::from_str("POINT (10 20.1)").ok().unwrap(); - match wkt.item { - Geometry::Point(Point(Some(coord))) => { + match wkt { + Wkt::Point(Point(Some(coord))) => { assert_eq!(coord.x, 10.0); assert_eq!(coord.y, 20.1); assert_eq!(coord.z, None); @@ -405,8 +384,8 @@ mod tests { // point(x, y, z) let wkt = >::from_str("POINTZ (10 20.1 5)").ok().unwrap(); - match wkt.item { - Geometry::Point(Point(Some(coord))) => { + match wkt { + Wkt::Point(Point(Some(coord))) => { assert_eq!(coord.x, 10.0); assert_eq!(coord.y, 20.1); assert_eq!(coord.z, Some(5.0)); @@ -417,8 +396,8 @@ mod tests { // point(x, y, m) let wkt = >::from_str("POINTM (10 20.1 80)").ok().unwrap(); - match wkt.item { - Geometry::Point(Point(Some(coord))) => { + match wkt { + Wkt::Point(Point(Some(coord))) => { assert_eq!(coord.x, 10.0); assert_eq!(coord.y, 20.1); assert_eq!(coord.z, None); @@ -429,8 +408,8 @@ mod tests { // 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))) => { + match wkt { + Wkt::Point(Point(Some(coord))) => { assert_eq!(coord.x, 10.0); assert_eq!(coord.y, 20.1); assert_eq!(coord.z, Some(5.0)); @@ -443,15 +422,15 @@ mod tests { #[test] fn support_jts_linearring() { let wkt: Wkt = Wkt::from_str("linearring (10 20, 30 40)").ok().unwrap(); - match wkt.item { - Geometry::LineString(_ls) => (), + match wkt { + Wkt::LineString(_ls) => (), _ => panic!("expected to be parsed as a LINESTRING"), }; } #[test] fn test_debug() { - let g = Geometry::Point(Point(Some(Coord { + let g = Wkt::Point(Point(Some(Coord { x: 1.0, y: 2.0, m: None, diff --git a/src/types/geometrycollection.rs b/src/types/geometrycollection.rs index b1e73a5..fd57235 100644 --- a/src/types/geometrycollection.rs +++ b/src/types/geometrycollection.rs @@ -13,19 +13,19 @@ // limitations under the License. use crate::tokenizer::{PeekableTokens, Token}; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] -pub struct GeometryCollection(pub Vec>); +pub struct GeometryCollection(pub Vec>); -impl GeometryCollection +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::GeometryCollection(self) + fn from(value: GeometryCollection) -> Self { + Wkt::GeometryCollection(value) } } @@ -61,7 +61,7 @@ where _ => return Err("Expected a word in GEOMETRYCOLLECTION"), }; - let item = Geometry::from_word_and_tokens(&word, tokens)?; + let item = Wkt::from_word_and_tokens(&word, tokens)?; items.push(item); while let Some(&Ok(Token::Comma)) = tokens.peek() { @@ -72,7 +72,7 @@ where _ => return Err("Expected a word in GEOMETRYCOLLECTION"), }; - let item = Geometry::from_word_and_tokens(&word, tokens)?; + let item = Wkt::from_word_and_tokens(&word, tokens)?; items.push(item); } @@ -84,7 +84,7 @@ where mod tests { use super::GeometryCollection; use crate::types::*; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] @@ -92,8 +92,8 @@ mod tests { let wkt: Wkt = Wkt::from_str("GEOMETRYCOLLECTION (POINT (8 4)))") .ok() .unwrap(); - let items = match wkt.item { - Geometry::GeometryCollection(GeometryCollection(items)) => items, + let items = match wkt { + Wkt::GeometryCollection(GeometryCollection(items)) => items, _ => unreachable!(), }; assert_eq!(1, items.len()); @@ -104,8 +104,8 @@ mod tests { let wkt: Wkt = Wkt::from_str("GEOMETRYCOLLECTION (POINT (8 4),LINESTRING(4 6,7 10)))") .ok() .unwrap(); - let items = match wkt.item { - Geometry::GeometryCollection(GeometryCollection(items)) => items, + let items = match wkt { + Wkt::GeometryCollection(GeometryCollection(items)) => items, _ => unreachable!(), }; assert_eq!(2, items.len()); @@ -123,14 +123,14 @@ mod tests { #[test] fn write_geometry_collection() { - let point = Geometry::Point(Point(Some(Coord { + let point = Wkt::Point(Point(Some(Coord { x: 10., y: 20., z: None, m: None, }))); - let multipoint = Geometry::MultiPoint(MultiPoint(vec![ + let multipoint = Wkt::MultiPoint(MultiPoint(vec![ Point(Some(Coord { x: 10.1, y: 20.2, @@ -145,7 +145,7 @@ mod tests { })), ])); - let linestring = Geometry::LineString(LineString(vec![ + let linestring = Wkt::LineString(LineString(vec![ Coord { x: 10., y: 20., @@ -160,7 +160,7 @@ mod tests { }, ])); - let polygon = Geometry::Polygon(Polygon(vec![LineString(vec![ + let polygon = Wkt::Polygon(Polygon(vec![LineString(vec![ Coord { x: 0., y: 0., @@ -187,7 +187,7 @@ mod tests { }, ])])); - let multilinestring = Geometry::MultiLineString(MultiLineString(vec![ + let multilinestring = Wkt::MultiLineString(MultiLineString(vec![ LineString(vec![ Coord { x: 10.1, @@ -218,7 +218,7 @@ mod tests { ]), ])); - let multipolygon = Geometry::MultiPolygon(MultiPolygon(vec![ + let multipolygon = Wkt::MultiPolygon(MultiPolygon(vec![ Polygon(vec![LineString(vec![ Coord { x: 0., diff --git a/src/types/linestring.rs b/src/types/linestring.rs index dfe6813..3cf99de 100644 --- a/src/types/linestring.rs +++ b/src/types/linestring.rs @@ -14,19 +14,19 @@ use crate::tokenizer::PeekableTokens; use crate::types::coord::Coord; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] pub struct LineString(pub Vec>); -impl LineString +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::LineString(self) + fn from(value: LineString) -> Self { + Wkt::LineString(value) } } @@ -63,14 +63,14 @@ where #[cfg(test)] mod tests { use super::{Coord, LineString}; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] fn basic_linestring() { let wkt = Wkt::from_str("LINESTRING (10 -20, -0 -0.5)").ok().unwrap(); - let coords = match wkt.item { - Geometry::LineString(LineString(coords)) => coords, + let coords = match wkt { + Wkt::LineString(LineString(coords)) => coords, _ => unreachable!(), }; assert_eq!(2, coords.len()); diff --git a/src/types/multilinestring.rs b/src/types/multilinestring.rs index 7a65a55..82e9e76 100644 --- a/src/types/multilinestring.rs +++ b/src/types/multilinestring.rs @@ -14,19 +14,19 @@ use crate::tokenizer::PeekableTokens; use crate::types::linestring::LineString; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] pub struct MultiLineString(pub Vec>); -impl MultiLineString +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::MultiLineString(self) + fn from(value: MultiLineString) -> Self { + Wkt::MultiLineString(value) } } @@ -72,7 +72,7 @@ where mod tests { use super::{LineString, MultiLineString}; use crate::types::Coord; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] @@ -80,8 +80,8 @@ mod tests { let wkt: Wkt = Wkt::from_str("MULTILINESTRING ((8 4, -3 0), (4 0, 6 -10))") .ok() .unwrap(); - let lines = match wkt.item { - Geometry::MultiLineString(MultiLineString(lines)) => lines, + let lines = match wkt { + Wkt::MultiLineString(MultiLineString(lines)) => lines, _ => unreachable!(), }; assert_eq!(2, lines.len()); diff --git a/src/types/multipoint.rs b/src/types/multipoint.rs index 051d206..44170b2 100644 --- a/src/types/multipoint.rs +++ b/src/types/multipoint.rs @@ -14,19 +14,19 @@ use crate::tokenizer::PeekableTokens; use crate::types::point::Point; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] pub struct MultiPoint(pub Vec>); -impl MultiPoint +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::MultiPoint(self) + fn from(value: MultiPoint) -> Self { + Wkt::MultiPoint(value) } } @@ -68,14 +68,14 @@ where mod tests { use super::{MultiPoint, Point}; use crate::types::Coord; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] fn basic_multipoint() { let wkt: Wkt = Wkt::from_str("MULTIPOINT ((8 4), (4 0))").ok().unwrap(); - let points = match wkt.item { - Geometry::MultiPoint(MultiPoint(points)) => points, + let points = match wkt { + Wkt::MultiPoint(MultiPoint(points)) => points, _ => unreachable!(), }; assert_eq!(2, points.len()); @@ -84,8 +84,8 @@ mod tests { #[test] fn postgis_style_multipoint() { let wkt: Wkt = Wkt::from_str("MULTIPOINT (8 4, 4 0)").unwrap(); - let points = match wkt.item { - Geometry::MultiPoint(MultiPoint(points)) => points, + let points = match wkt { + Wkt::MultiPoint(MultiPoint(points)) => points, _ => unreachable!(), }; assert_eq!(2, points.len()); @@ -94,8 +94,8 @@ mod tests { #[test] fn mixed_parens_multipoint() { let wkt: Wkt = Wkt::from_str("MULTIPOINT (8 4, (4 0))").unwrap(); - let points = match wkt.item { - Geometry::MultiPoint(MultiPoint(points)) => points, + let points = match wkt { + Wkt::MultiPoint(MultiPoint(points)) => points, _ => unreachable!(), }; assert_eq!(2, points.len()); @@ -104,8 +104,8 @@ mod tests { #[test] fn empty_multipoint() { let wkt: Wkt = Wkt::from_str("MULTIPOINT EMPTY").unwrap(); - let points = match wkt.item { - Geometry::MultiPoint(MultiPoint(points)) => points, + let points = match wkt { + Wkt::MultiPoint(MultiPoint(points)) => points, _ => unreachable!(), }; assert_eq!(0, points.len()); diff --git a/src/types/multipolygon.rs b/src/types/multipolygon.rs index b76956b..706a493 100644 --- a/src/types/multipolygon.rs +++ b/src/types/multipolygon.rs @@ -14,19 +14,19 @@ use crate::tokenizer::PeekableTokens; use crate::types::polygon::Polygon; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] pub struct MultiPolygon(pub Vec>); -impl MultiPolygon +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::MultiPolygon(self) + fn from(value: MultiPolygon) -> Self { + Wkt::MultiPolygon(value) } } @@ -77,7 +77,7 @@ where mod tests { use super::{MultiPolygon, Polygon}; use crate::types::{Coord, LineString}; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] @@ -85,8 +85,8 @@ mod tests { let wkt: Wkt = Wkt::from_str("MULTIPOLYGON (((8 4)), ((4 0)))") .ok() .unwrap(); - let polygons = match wkt.item { - Geometry::MultiPolygon(MultiPolygon(polygons)) => polygons, + let polygons = match wkt { + Wkt::MultiPolygon(MultiPolygon(polygons)) => polygons, _ => unreachable!(), }; assert_eq!(2, polygons.len()); diff --git a/src/types/point.rs b/src/types/point.rs index 66b3ebc..4521b9d 100644 --- a/src/types/point.rs +++ b/src/types/point.rs @@ -14,19 +14,19 @@ use crate::tokenizer::PeekableTokens; use crate::types::coord::Coord; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] pub struct Point(pub Option>); -impl Point +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::Point(self) + fn from(value: Point) -> Self { + Wkt::Point(value) } } @@ -68,14 +68,14 @@ where #[cfg(test)] mod tests { use super::{Coord, Point}; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] fn basic_point() { let wkt = Wkt::from_str("POINT (10 -20)").ok().unwrap(); - let coord = match wkt.item { - Geometry::Point(Point(Some(coord))) => coord, + let coord = match wkt { + Wkt::Point(Point(Some(coord))) => coord, _ => unreachable!(), }; assert_eq!(10.0, coord.x); @@ -89,8 +89,8 @@ mod tests { let wkt: Wkt = Wkt::from_str(" \n\t\rPOINT \n\t\r( \n\r\t10 \n\t\r-20 \n\t\r) \n\t\r") .ok() .unwrap(); - let coord = match wkt.item { - Geometry::Point(Point(Some(coord))) => coord, + let coord = match wkt { + Wkt::Point(Point(Some(coord))) => coord, _ => unreachable!(), }; assert_eq!(10.0, coord.x); diff --git a/src/types/polygon.rs b/src/types/polygon.rs index 1c778c2..5e547a5 100644 --- a/src/types/polygon.rs +++ b/src/types/polygon.rs @@ -14,19 +14,19 @@ use crate::tokenizer::PeekableTokens; use crate::types::linestring::LineString; -use crate::{FromTokens, Geometry, WktNum}; +use crate::{FromTokens, Wkt, WktNum}; use std::fmt; use std::str::FromStr; #[derive(Clone, Debug, Default, PartialEq)] pub struct Polygon(pub Vec>); -impl Polygon +impl From> for Wkt where T: WktNum, { - pub fn as_item(self) -> Geometry { - Geometry::Polygon(self) + fn from(value: Polygon) -> Self { + Wkt::Polygon(value) } } @@ -72,7 +72,7 @@ where mod tests { use super::{LineString, Polygon}; use crate::types::Coord; - use crate::{Geometry, Wkt}; + use crate::Wkt; use std::str::FromStr; #[test] @@ -80,8 +80,8 @@ mod tests { let wkt: Wkt = Wkt::from_str("POLYGON ((8 4, 4 0, 0 4, 8 4), (7 3, 4 1, 1 4, 7 3))") .ok() .unwrap(); - let lines = match wkt.item { - Geometry::Polygon(Polygon(lines)) => lines, + let lines = match wkt { + Wkt::Polygon(Polygon(lines)) => lines, _ => unreachable!(), }; assert_eq!(2, lines.len());