From 80f0812ccf092a640cb0920130d73efa3e21a6a4 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 7 Oct 2024 22:49:23 -0400 Subject: [PATCH] Switch to ryu --- Cargo.toml | 1 + src/geo_types_from_wkt.rs | 40 ++++++++-------- src/geo_types_to_wkt.rs | 81 +++++++++++++++++++-------------- src/lib.rs | 62 +++++++++++++++++-------- src/to_wkt.rs | 1 + src/types/coord.rs | 70 ++++++++++++++++++++++------ src/types/geometrycollection.rs | 50 ++++++++++++-------- src/types/linestring.rs | 48 ++++++++++++------- src/types/point.rs | 58 ++++++++++++++--------- 9 files changed, 267 insertions(+), 144 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 228941f..77c0c8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ num-traits = "0.2" serde = { version = "1.0", default-features = false, optional = true } thiserror = "1.0.23" log = "0.4.17" +ryu = "1.0" [dev-dependencies] criterion = "0.5.1" diff --git a/src/geo_types_from_wkt.rs b/src/geo_types_from_wkt.rs index b89cf32..ec275ae 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::{TryFromWkt, Wkt}; +use crate::{TryFromWkt, Wkt, WktNum}; use std::any::type_name; use std::convert::{TryFrom, TryInto}; @@ -48,7 +48,7 @@ macro_rules! try_from_wkt_impl { ($($type: ident),+) => { $( /// Fallibly convert this WKT primitive into this [`geo_types`] primitive - impl TryFrom> for geo_types::$type { + impl TryFrom> for geo_types::$type { type Error = Error; fn try_from(wkt: Wkt) -> Result { @@ -84,7 +84,7 @@ try_from_wkt_impl!( ); /// Fallibly convert this WKT primitive into this [`geo_types`] primitive -impl TryFrom> for geo_types::GeometryCollection { +impl TryFrom> for geo_types::GeometryCollection { type Error = Error; fn try_from(wkt: Wkt) -> Result { @@ -127,7 +127,7 @@ impl TryFrom> for geo_types::GeometryCollection { impl From> for geo_types::Coord where - T: CoordNum, + T: CoordNum + WktNum, { /// Convert from a WKT Coordinate to a [`geo_types::Coordinate`] fn from(coord: Coord) -> geo_types::Coord { @@ -137,7 +137,7 @@ where impl TryFrom> for geo_types::Point where - T: CoordNum, + T: CoordNum + WktNum, { type Error = Error; @@ -153,14 +153,14 @@ where #[deprecated(since = "0.9.0", note = "use `geometry.try_into()` instead")] pub fn try_into_geometry(geometry: &Wkt) -> Result, Error> where - T: CoordNum, + T: CoordNum + WktNum, { geometry.clone().try_into() } impl<'a, T> From<&'a LineString> for geo_types::Geometry where - T: CoordNum, + T: CoordNum + WktNum, { fn from(line_string: &'a LineString) -> Self { Self::LineString(line_string.clone().into()) @@ -169,7 +169,7 @@ where impl From> for geo_types::LineString where - T: CoordNum, + T: CoordNum + WktNum, { /// Convert from a WKT `LINESTRING` to a [`geo_types::LineString`] fn from(line_string: LineString) -> Self { @@ -185,7 +185,7 @@ where impl<'a, T> From<&'a MultiLineString> for geo_types::Geometry where - T: CoordNum, + T: CoordNum + WktNum, { fn from(multi_line_string: &'a MultiLineString) -> geo_types::Geometry { Self::MultiLineString(multi_line_string.clone().into()) @@ -194,7 +194,7 @@ where impl From> for geo_types::MultiLineString where - T: CoordNum, + T: CoordNum + WktNum, { /// Convert from a WKT `MULTILINESTRING` to a [`geo_types::MultiLineString`] fn from(multi_line_string: MultiLineString) -> geo_types::MultiLineString { @@ -210,7 +210,7 @@ where impl<'a, T> From<&'a Polygon> for geo_types::Geometry where - T: CoordNum, + T: CoordNum + WktNum, { fn from(polygon: &'a Polygon) -> geo_types::Geometry { Self::Polygon(polygon.clone().into()) @@ -219,7 +219,7 @@ where impl From> for geo_types::Polygon where - T: CoordNum, + T: CoordNum + WktNum, { /// Convert from a WKT `POLYGON` to a [`geo_types::Polygon`] fn from(polygon: Polygon) -> Self { @@ -233,7 +233,7 @@ where impl<'a, T> TryFrom<&'a MultiPoint> for geo_types::Geometry where - T: CoordNum, + T: CoordNum + WktNum, { type Error = Error; @@ -244,7 +244,7 @@ where impl TryFrom> for geo_types::MultiPoint where - T: CoordNum, + T: CoordNum + WktNum, { type Error = Error; /// Fallibly convert from a WKT `MULTIPOINT` to a [`geo_types::MultiPoint`] @@ -261,7 +261,7 @@ where impl<'a, T> From<&'a MultiPolygon> for geo_types::Geometry where - T: CoordNum, + T: CoordNum + WktNum, { fn from(multi_polygon: &'a MultiPolygon) -> Self { Self::MultiPolygon(multi_polygon.clone().into()) @@ -270,7 +270,7 @@ where impl From> for geo_types::MultiPolygon where - T: CoordNum, + T: CoordNum + WktNum, { /// Convert from a WKT `MULTIPOLYGON` to a [`geo_types::MultiPolygon`] fn from(multi_polygon: MultiPolygon) -> Self { @@ -289,7 +289,7 @@ pub fn try_into_geometry_collection( geometry_collection: &GeometryCollection, ) -> Result, Error> where - T: CoordNum, + T: CoordNum + WktNum, { Ok(geo_types::Geometry::GeometryCollection( geometry_collection.clone().try_into()?, @@ -298,7 +298,7 @@ where impl TryFrom> for geo_types::GeometryCollection where - T: CoordNum, + T: CoordNum + WktNum, { type Error = Error; @@ -315,7 +315,7 @@ where impl TryFrom> for geo_types::Geometry where - T: CoordNum, + T: CoordNum + WktNum, { type Error = Error; @@ -348,7 +348,7 @@ where macro_rules! try_from_wkt_impl { ($($type: ty),*$(,)?) => { $( - impl TryFromWkt for $type { + impl TryFromWkt for $type { type Error = Error; fn try_from_wkt_str(wkt_str: &str) -> Result { let wkt = Wkt::from_str(wkt_str).map_err(|e| Error::InvalidWKT(e))?; diff --git a/src/geo_types_to_wkt.rs b/src/geo_types_to_wkt.rs index e664ae3..f8c9431 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::{ToWkt, Wkt}; +use crate::{ToWkt, Wkt, WktNum}; /// # Examples /// ``` @@ -13,11 +13,12 @@ use crate::{ToWkt, Wkt}; /// /// let geometry: Geometry = Geometry::Point(point!(x: 1., y: 2.)); /// -/// assert_eq!(geometry.wkt_string(), "POINT(1 2)"); +/// assert_eq!(geometry.wkt_string(), "POINT(1.0 2.0)"); /// ``` impl ToWkt for geo_types::Geometry where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { match self { @@ -42,11 +43,12 @@ where /// /// let point: Point = point!(x: 1., y: 2.); /// -/// assert_eq!(point.wkt_string(), "POINT(1 2)"); +/// assert_eq!(point.wkt_string(), "POINT(1.0 2.0)"); /// ``` impl ToWkt for geo_types::Point where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { Wkt::Point(g_point_to_w_point(self)) @@ -60,11 +62,12 @@ where /// /// let line = Line::::new(coord!(x: 1., y: 2.), coord!(x: 3., y: 4.)); /// -/// assert_eq!(line.wkt_string(), "LINESTRING(1 2,3 4)"); +/// assert_eq!(line.wkt_string(), "LINESTRING(1.0 2.0,3.0 4.0)"); /// ``` impl ToWkt for geo_types::Line where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_line_to_w_linestring(self).into() @@ -78,11 +81,12 @@ where /// /// let line_string: LineString = line_string![(x: 1., y: 2.), (x: 3., y: 4.), (x: 5., y: 6.)]; /// -/// assert_eq!(line_string.wkt_string(), "LINESTRING(1 2,3 4,5 6)"); +/// assert_eq!(line_string.wkt_string(), "LINESTRING(1.0 2.0,3.0 4.0,5.0 6.0)"); /// ``` impl ToWkt for geo_types::LineString where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_linestring_to_w_linestring(self).into() @@ -100,7 +104,8 @@ where /// ``` impl ToWkt for geo_types::Polygon where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_polygon_to_w_polygon(self).into() @@ -118,7 +123,8 @@ where /// ``` impl ToWkt for geo_types::MultiPoint where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_mpoint_to_w_mpoint(self).into() @@ -138,7 +144,8 @@ where /// ``` impl ToWkt for geo_types::MultiLineString where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_mline_to_w_mline(self).into() @@ -160,7 +167,8 @@ where /// ``` impl ToWkt for geo_types::MultiPolygon where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_mpolygon_to_w_mpolygon(self).into() @@ -176,11 +184,12 @@ where /// let line_string: LineString = line_string![(x: 1., y: 2.), (x: 3., y: 4.), (x: 5., y: 6.)]; /// let geometry_collection: GeometryCollection = GeometryCollection::new_from(vec![polygon.into(), line_string.into()]); /// -/// assert_eq!(geometry_collection.wkt_string(), "GEOMETRYCOLLECTION(POLYGON((0 0,4 0,2 4,0 0)),LINESTRING(1 2,3 4,5 6))"); +/// assert_eq!(geometry_collection.wkt_string(), "GEOMETRYCOLLECTION(POLYGON((0 0,4 0,2 4,0 0)),LINESTRING(1.0 2.0,3.0 4.0,5.0 6.0))"); /// ``` impl ToWkt for geo_types::GeometryCollection where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_geocol_to_w_geocol(self).into() @@ -198,7 +207,8 @@ where /// ``` impl ToWkt for geo_types::Rect where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_rect_to_w_polygon(self).into() @@ -216,7 +226,8 @@ where /// ``` impl ToWkt for geo_types::Triangle where - T: CoordNum + std::fmt::Display, + T: CoordNum + std::fmt::Display + WktNum, + Wkt: std::fmt::Display, { fn to_wkt(&self) -> Wkt { g_triangle_to_w_polygon(self).into() @@ -225,7 +236,7 @@ where fn g_point_to_w_coord(g_point: &geo_types::Coord) -> Coord where - T: CoordNum, + T: CoordNum + WktNum, { Coord { x: g_point.x, @@ -237,7 +248,7 @@ where fn g_point_to_w_point(g_point: &geo_types::Point) -> Point where - T: CoordNum, + T: CoordNum + WktNum, { let coord = g_point_to_w_coord(&g_point.0); Point(Some(coord)) @@ -245,14 +256,14 @@ where fn g_points_to_w_coords(g_points: &[geo_types::Coord]) -> Vec> where - T: CoordNum, + T: CoordNum + WktNum, { g_points.iter().map(g_point_to_w_coord).collect() } fn g_points_to_w_points(g_points: &[geo_types::Point]) -> Vec> where - T: CoordNum, + T: CoordNum + WktNum, { g_points .iter() @@ -264,14 +275,14 @@ where fn g_line_to_w_linestring(g_line: &geo_types::Line) -> LineString where - T: CoordNum, + T: CoordNum + WktNum, { g_points_to_w_linestring(&[g_line.start, g_line.end]) } fn g_linestring_to_w_linestring(g_linestring: &geo_types::LineString) -> LineString where - T: CoordNum, + T: CoordNum + WktNum, { let geo_types::LineString(g_points) = g_linestring; g_points_to_w_linestring(g_points) @@ -279,7 +290,7 @@ where fn g_points_to_w_linestring(g_coords: &[geo_types::Coord]) -> LineString where - T: CoordNum, + T: CoordNum + WktNum, { let w_coords = g_points_to_w_coords(g_coords); LineString(w_coords) @@ -287,7 +298,7 @@ where fn g_lines_to_w_lines(g_lines: &[geo_types::LineString]) -> Vec> where - T: CoordNum, + T: CoordNum + WktNum, { let mut w_lines = vec![]; for g_line in g_lines { @@ -299,7 +310,7 @@ where fn g_triangle_to_w_polygon(g_triangle: &geo_types::Triangle) -> Polygon where - T: CoordNum, + T: CoordNum + WktNum, { let polygon = g_triangle.to_polygon(); g_polygon_to_w_polygon(&polygon) @@ -307,7 +318,7 @@ where fn g_rect_to_w_polygon(g_rect: &geo_types::Rect) -> Polygon where - T: CoordNum, + T: CoordNum + WktNum, { let polygon = g_rect.to_polygon(); g_polygon_to_w_polygon(&polygon) @@ -315,7 +326,7 @@ where fn g_polygon_to_w_polygon(g_polygon: &geo_types::Polygon) -> Polygon where - T: CoordNum, + T: CoordNum + WktNum, { let outer_line = g_polygon.exterior(); let inner_lines = g_polygon.interiors(); @@ -336,7 +347,7 @@ where fn g_mpoint_to_w_mpoint(g_mpoint: &geo_types::MultiPoint) -> MultiPoint where - T: CoordNum, + T: CoordNum + WktNum, { let geo_types::MultiPoint(g_points) = g_mpoint; let w_points = g_points_to_w_points(g_points); @@ -345,7 +356,7 @@ where fn g_mline_to_w_mline(g_mline: &geo_types::MultiLineString) -> MultiLineString where - T: CoordNum, + T: CoordNum + WktNum, { let geo_types::MultiLineString(g_lines) = g_mline; let w_lines = g_lines_to_w_lines(g_lines); @@ -354,7 +365,7 @@ where fn g_polygons_to_w_polygons(g_polygons: &[geo_types::Polygon]) -> Vec> where - T: CoordNum, + T: CoordNum + WktNum, { let mut w_polygons = vec![]; for g_polygon in g_polygons { @@ -365,7 +376,7 @@ where fn g_mpolygon_to_w_mpolygon(g_mpolygon: &geo_types::MultiPolygon) -> MultiPolygon where - T: CoordNum, + T: CoordNum + WktNum, { let geo_types::MultiPolygon(g_polygons) = g_mpolygon; let w_polygons = g_polygons_to_w_polygons(g_polygons); @@ -374,7 +385,7 @@ where fn g_geocol_to_w_geocol(g_geocol: &geo_types::GeometryCollection) -> GeometryCollection where - T: CoordNum, + T: CoordNum + WktNum, { let geo_types::GeometryCollection(g_geoms) = g_geocol; let mut w_geoms = vec![]; @@ -387,7 +398,7 @@ where fn g_geom_to_w_geom(g_geom: &geo_types::Geometry) -> Wkt where - T: CoordNum, + T: CoordNum + WktNum, { match *g_geom { geo_types::Geometry::Point(ref g_point) => g_point_to_w_point(g_point).into(), @@ -429,7 +440,7 @@ mod tests { #[test] fn float_geom() { let point = geo_types::Point::new(1f32, 2f32); - assert_eq!("POINT(1 2)", &point.wkt_string()); + assert_eq!("POINT(1.0 2.0)", &point.wkt_string()); let point = geo_types::Point::new(1.1f32, 2.9f32); assert_eq!("POINT(1.1 2.9)", &point.wkt_string()); diff --git a/src/lib.rs b/src/lib.rs index ee6d881..ea7379c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,7 +50,7 @@ //! use geo_types::Point; //! //! let point: Point = Point::new(1.0, 2.0); -//! assert_eq!(point.wkt_string(), "POINT(1 2)"); +//! assert_eq!(point.wkt_string(), "POINT(1.0 2.0)"); //! ``` //! //! ## Read or write your own geometry types @@ -135,10 +135,22 @@ pub use deserialize::geo_types::deserialize_geometry; pub use deserialize::geo_types::deserialize_point; pub trait WktNum: Num + NumCast + PartialOrd + PartialEq + Copy + fmt::Debug {} -impl WktNum for T where T: Num + NumCast + PartialOrd + PartialEq + Copy + fmt::Debug {} +impl WktNum for f32 {} +impl WktNum for f64 {} +impl WktNum for u8 {} +impl WktNum for u16 {} +impl WktNum for u32 {} +impl WktNum for u64 {} +impl WktNum for usize {} +impl WktNum for i8 {} +impl WktNum for i16 {} +impl WktNum for i32 {} +impl WktNum for i64 {} +impl WktNum for isize {} pub trait WktFloat: WktNum + Float {} -impl WktFloat for T where T: WktNum + Float {} +impl WktFloat for f32 {} +impl WktFloat for f64 {} #[derive(Clone, Debug, PartialEq)] /// All supported WKT geometry [`types`] @@ -350,23 +362,37 @@ where } } -impl fmt::Display for Wkt -where - T: WktNum + fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self { - 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), +macro_rules! impl_display { + ($t: ident) => { + impl fmt::Display for Wkt<$t> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match self { + 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), + } + } } - } + }; } +impl_display!(f32); +impl_display!(f64); +impl_display!(u8); +impl_display!(u16); +impl_display!(u32); +impl_display!(u64); +impl_display!(usize); +impl_display!(i8); +impl_display!(i16); +impl_display!(i32); +impl_display!(i64); +impl_display!(isize); + impl Wkt where T: WktNum + FromStr + Default, @@ -629,6 +655,6 @@ mod tests { fn test_display_on_wkt() { let wktls: Wkt = Wkt::from_str("LINESTRING(10 20, 20 30)").unwrap(); - assert_eq!(wktls.to_string(), "LINESTRING(10 20,20 30)"); + assert_eq!(wktls.to_string(), "LINESTRING(10.0 20.0,20.0 30.0)"); } } diff --git a/src/to_wkt.rs b/src/to_wkt.rs index 8219d5c..c24719d 100644 --- a/src/to_wkt.rs +++ b/src/to_wkt.rs @@ -4,6 +4,7 @@ use crate::{Wkt, WktNum}; pub trait ToWkt where T: WktNum + std::fmt::Display, + Wkt: std::fmt::Display, { /// Converts the value of `self` to an [`Wkt`] struct. /// diff --git a/src/types/coord.rs b/src/types/coord.rs index 358490e..f24e09d 100644 --- a/src/types/coord.rs +++ b/src/types/coord.rs @@ -29,22 +29,64 @@ where pub m: Option, } -impl fmt::Display for Coord -where - T: WktNum + fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{} {}", self.x, self.y)?; - if let Some(z) = self.z { - write!(f, " {}", z)?; +macro_rules! impl_display_for_float { + ($t: ident) => { + impl fmt::Display for Coord<$t> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let mut buffer = ryu::Buffer::new(); + let x = buffer.format(self.x); + + let mut buffer = ryu::Buffer::new(); + let y = buffer.format(self.y); + + write!(f, "{} {}", x, y)?; + if let Some(z) = self.z { + let mut buffer = ryu::Buffer::new(); + let z = buffer.format(z); + write!(f, " {}", z)?; + } + if let Some(m) = self.m { + let mut buffer = ryu::Buffer::new(); + let m = buffer.format(m); + write!(f, " {}", m)?; + } + Ok(()) + } } - if let Some(m) = self.m { - write!(f, " {}", m)?; + }; +} + +macro_rules! impl_display_for_int { + ($t: ident) => { + impl fmt::Display for Coord<$t> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{} {}", self.x, self.y)?; + if let Some(z) = self.z { + write!(f, " {}", z)?; + } + if let Some(m) = self.m { + write!(f, " {}", m)?; + } + Ok(()) + } } - Ok(()) - } + }; } +impl_display_for_float!(f32); +impl_display_for_float!(f64); + +impl_display_for_int!(u8); +impl_display_for_int!(u16); +impl_display_for_int!(u32); +impl_display_for_int!(u64); +impl_display_for_int!(usize); +impl_display_for_int!(i8); +impl_display_for_int!(i16); +impl_display_for_int!(i32); +impl_display_for_int!(i64); +impl_display_for_int!(isize); + impl FromTokens for Coord where T: WktNum + FromStr + Default, @@ -133,7 +175,7 @@ mod tests { m: Some(10.), }; - assert_eq!("10.1 20.2 10", format!("{}", coord)); + assert_eq!("10.1 20.2 10.0", format!("{}", coord)); } #[test] @@ -145,6 +187,6 @@ mod tests { m: Some(10.), }; - assert_eq!("10.1 20.2 -30.3 10", format!("{}", coord)); + assert_eq!("10.1 20.2 -30.3 10.0", format!("{}", coord)); } } diff --git a/src/types/geometrycollection.rs b/src/types/geometrycollection.rs index 8aa3d8a..cd5fbf4 100644 --- a/src/types/geometrycollection.rs +++ b/src/types/geometrycollection.rs @@ -30,26 +30,40 @@ where } } -impl fmt::Display for GeometryCollection -where - T: WktNum + fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - if self.0.is_empty() { - f.write_str("GEOMETRYCOLLECTION EMPTY") - } else { - let strings = self - .0 - .iter() - .map(|geometry| format!("{}", geometry)) - .collect::>() - .join(","); +macro_rules! impl_display { + ($t: ident) => { + impl fmt::Display for GeometryCollection<$t> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + if self.0.is_empty() { + f.write_str("GEOMETRYCOLLECTION EMPTY") + } else { + let strings = self + .0 + .iter() + .map(|geometry| format!("{}", geometry)) + .collect::>() + .join(","); - write!(f, "GEOMETRYCOLLECTION({})", strings) + write!(f, "GEOMETRYCOLLECTION({})", strings) + } + } } - } + }; } +impl_display!(f32); +impl_display!(f64); +impl_display!(u8); +impl_display!(u16); +impl_display!(u32); +impl_display!(u64); +impl_display!(usize); +impl_display!(i8); +impl_display!(i16); +impl_display!(i32); +impl_display!(i64); +impl_display!(isize); + impl FromTokens for GeometryCollection where T: WktNum + FromStr + Default, @@ -288,9 +302,9 @@ mod tests { assert_eq!( "GEOMETRYCOLLECTION(\ - POINT(10 20),\ + POINT(10.0 20.0),\ MULTIPOINT((10.1 20.2),(30.3 40.4)),\ - LINESTRING(10 20,30 40),\ + LINESTRING(10.0 20.0,30.0 40.0),\ POLYGON((0 0,20 40,40 0,0 0)),\ MULTILINESTRING((10.1 20.2,30.3 40.4),(50.5 60.6,70.7 80.8)),\ MULTIPOLYGON(((0 0,20 40,40 0,0 0)),((40 40,20 45,45 30,40 40)))\ diff --git a/src/types/linestring.rs b/src/types/linestring.rs index ff84bcf..4ea2e5a 100644 --- a/src/types/linestring.rs +++ b/src/types/linestring.rs @@ -41,26 +41,40 @@ where } } -impl fmt::Display for LineString -where - T: WktNum + fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - if self.0.is_empty() { - f.write_str("LINESTRING EMPTY") - } else { - let strings = self - .0 - .iter() - .map(|c| format!("{}", c)) - .collect::>() - .join(","); - - write!(f, "LINESTRING({})", strings) +macro_rules! impl_display { + ($t: ident) => { + impl fmt::Display for LineString<$t> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + if self.0.is_empty() { + f.write_str("LINESTRING EMPTY") + } else { + let strings = self + .0 + .iter() + .map(|c| format!("{}", c)) + .collect::>() + .join(","); + + write!(f, "LINESTRING({})", strings) + } + } } - } + }; } +impl_display!(f32); +impl_display!(f64); +impl_display!(u8); +impl_display!(u16); +impl_display!(u32); +impl_display!(u64); +impl_display!(usize); +impl_display!(i8); +impl_display!(i16); +impl_display!(i32); +impl_display!(i64); +impl_display!(isize); + #[cfg(test)] mod tests { use super::{Coord, LineString}; diff --git a/src/types/point.rs b/src/types/point.rs index a4d6123..003294e 100644 --- a/src/types/point.rs +++ b/src/types/point.rs @@ -31,31 +31,45 @@ where } } -impl fmt::Display for Point -where - T: WktNum + fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self.0 { - Some(ref coord) => { - let mut lrs = String::new(); - if coord.z.is_some() { - lrs += "Z"; - } - if coord.m.is_some() { - lrs += "M"; - } - if !lrs.is_empty() { - lrs = " ".to_string() + &lrs; +macro_rules! impl_display { + ($t: ident) => { + impl fmt::Display for Point<$t> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match self.0 { + Some(ref coord) => { + let mut lrs = String::new(); + if coord.z.is_some() { + lrs += "Z"; + } + if coord.m.is_some() { + lrs += "M"; + } + if !lrs.is_empty() { + lrs = " ".to_string() + &lrs; + } + + write!(f, "POINT{}({})", lrs, coord) + } + None => f.write_str("POINT EMPTY"), } - - write!(f, "POINT{}({})", lrs, coord) } - None => f.write_str("POINT EMPTY"), } - } + }; } +impl_display!(f32); +impl_display!(f64); +impl_display!(u8); +impl_display!(u16); +impl_display!(u32); +impl_display!(u64); +impl_display!(usize); +impl_display!(i8); +impl_display!(i16); +impl_display!(i32); +impl_display!(i64); +impl_display!(isize); + impl FromTokens for Point where T: WktNum + FromStr + Default, @@ -173,7 +187,7 @@ mod tests { m: Some(10.), })); - assert_eq!("POINT M(10.12345 20.67891 10)", format!("{}", point)); + assert_eq!("POINT M(10.12345 20.67891 10.0)", format!("{}", point)); } #[test] @@ -186,7 +200,7 @@ mod tests { })); assert_eq!( - "POINT ZM(10.12345 20.67891 -32.56455 10)", + "POINT ZM(10.12345 20.67891 -32.56455 10.0)", format!("{}", point) ); }