diff --git a/Cargo.toml b/Cargo.toml index eaa8c16..e79b7d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ serde_json = "~1.0" geo-types = { version = "0.7", features = ["serde"], optional = true } thiserror = "1.0.20" log = "0.4.17" +tinyvec = { version = "1.6.0", features = ["serde", "alloc"] } [dev-dependencies] num-traits = "0.2" diff --git a/README.md b/README.md index 0ba4ce4..31ec18b 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ let geojson = geojson_str.parse::().unwrap(); use geojson::{Feature, GeoJson, Geometry, Value, JsonObject, JsonValue}; let geometry = Geometry::new( - Value::Point(vec![-120.66029,35.2812]) + Value::Point(Position::from([-120.66029,35.2812])) ); let mut properties = JsonObject::new(); diff --git a/src/conversion/from_geo_types.rs b/src/conversion/from_geo_types.rs index ec05d87..d1550a4 100644 --- a/src/conversion/from_geo_types.rs +++ b/src/conversion/from_geo_types.rs @@ -185,8 +185,7 @@ where { let x: f64 = point.x().to_f64().unwrap(); let y: f64 = point.y().to_f64().unwrap(); - - vec![x, y] + crate::Position::from([x, y]) } fn create_line_string_type(line_string: &geo_types::LineString) -> LineStringType diff --git a/src/conversion/to_geo_types.rs b/src/conversion/to_geo_types.rs index 996a730..775697e 100644 --- a/src/conversion/to_geo_types.rs +++ b/src/conversion/to_geo_types.rs @@ -361,15 +361,15 @@ fn mismatch_geom_err(expected_type: &'static str, found: &geometry::Value) -> Er #[cfg(test)] mod tests { - use crate::{Geometry, Value}; + use crate::{Geometry, Position, Value}; use serde_json::json; use std::convert::TryInto; #[test] fn geojson_point_conversion_test() { - let coords = vec![100.0, 0.2]; - let geojson_point = Value::Point(coords.clone()); + let coords = [100.0, 0.2]; + let geojson_point = Value::Point(Position(coords.clone().into())); let geo_point: geo_types::Point = geojson_point.try_into().unwrap(); assert_almost_eq!(geo_point.x(), coords[0], 1e-6); @@ -378,8 +378,8 @@ mod tests { #[test] fn geojson_multi_point_conversion_test() { - let coord1 = vec![100.0, 0.2]; - let coord2 = vec![101.0, 1.0]; + let coord1 = Position([100.0, 0.2].into()); + let coord2 = Position([101.0, 1.0].into()); let geojson_multi_point = Value::MultiPoint(vec![coord1.clone(), coord2.clone()]); let geo_multi_point: geo_types::MultiPoint = geojson_multi_point.try_into().unwrap(); @@ -391,8 +391,8 @@ mod tests { #[test] fn geojson_line_string_conversion_test() { - let coord1 = vec![100.0, 0.2]; - let coord2 = vec![101.0, 1.0]; + let coord1 = Position::from([100.0, 0.2]); + let coord2 = Position::from([101.0, 1.0]); let geojson_line_string = Value::LineString(vec![coord1.clone(), coord2.clone()]); let geo_line_string: geo_types::LineString = geojson_line_string.try_into().unwrap(); @@ -404,9 +404,9 @@ mod tests { #[test] fn geojson_multi_line_string_conversion_test() { - let coord1 = vec![100.0, 0.2]; - let coord2 = vec![101.0, 1.0]; - let coord3 = vec![102.0, 0.8]; + let coord1 = Position::from([100.0, 0.2]); + let coord2 = Position::from([101.0, 1.0]); + let coord3 = Position::from([102.0, 0.8]); let geojson_multi_line_string = Value::MultiLineString(vec![ vec![coord1.clone(), coord2.clone()], vec![coord2.clone(), coord3.clone()], @@ -429,12 +429,12 @@ mod tests { #[test] fn geojson_polygon_conversion_test() { - let coord1 = vec![100.0, 0.0]; - let coord2 = vec![101.0, 1.0]; - let coord3 = vec![101.0, 1.0]; - let coord4 = vec![104.0, 0.2]; - let coord5 = vec![100.9, 0.2]; - let coord6 = vec![100.9, 0.7]; + let coord1 = Position::from([100.0, 0.0]); + let coord2 = Position::from([101.0, 1.0]); + let coord3 = Position::from([101.0, 1.0]); + let coord4 = Position::from([104.0, 0.2]); + let coord5 = Position::from([100.9, 0.2]); + let coord6 = Position::from([100.9, 0.7]); let geojson_multi_line_string_type1 = vec![ vec![ @@ -484,9 +484,9 @@ mod tests { #[test] fn geojson_polygon_without_interiors_conversion_test() { - let coord1 = vec![100.0, 0.0]; - let coord2 = vec![101.0, 1.0]; - let coord3 = vec![101.0, 1.0]; + let coord1 = Position::from([100.0, 0.0]); + let coord2 = Position::from([101.0, 1.0]); + let coord3 = Position::from([101.0, 1.0]); let geojson_multi_line_string_type1 = vec![vec![ coord1.clone(), @@ -512,12 +512,12 @@ mod tests { #[test] fn geojson_multi_polygon_conversion_test() { - let coord1 = vec![100.0, 0.0]; - let coord2 = vec![101.0, 1.0]; - let coord3 = vec![101.0, 1.0]; - let coord4 = vec![104.0, 0.2]; - let coord5 = vec![100.9, 0.2]; - let coord6 = vec![100.9, 0.7]; + let coord1 = Position::from([100.0, 0.0]); + let coord2 = Position::from([101.0, 1.0]); + let coord3 = Position::from([101.0, 1.0]); + let coord4 = Position::from([104.0, 0.2]); + let coord5 = Position::from([100.9, 0.2]); + let coord6 = Position::from([100.9, 0.7]); let geojson_line_string_type1 = vec![ coord1.clone(), @@ -562,11 +562,11 @@ mod tests { #[test] fn geojson_geometry_collection_conversion_test() { - let coord1 = vec![100.0, 0.0]; - let coord2 = vec![100.0, 1.0]; - let coord3 = vec![101.0, 1.0]; - let coord4 = vec![102.0, 0.0]; - let coord5 = vec![101.0, 0.0]; + let coord1 = Position::from([100.0, 0.0]); + let coord2 = Position::from([100.0, 1.0]); + let coord3 = Position::from([101.0, 1.0]); + let coord4 = Position::from([102.0, 0.0]); + let coord5 = Position::from([101.0, 0.0]); let geojson_multi_point = Value::MultiPoint(vec![coord1.clone(), coord2.clone()]); let geojson_multi_line_string = Value::MultiLineString(vec![ @@ -602,7 +602,7 @@ mod tests { #[test] fn geojson_geometry_conversion() { - let coords = vec![100.0, 0.2]; + let coords = Position::from([100.0, 0.2]); let geojson_geometry = Geometry::from(Value::Point(coords.clone())); let geo_geometry: geo_types::Geometry = geojson_geometry .try_into() @@ -615,8 +615,8 @@ mod tests { #[test] fn geojson_mismatch_geometry_conversion_test() { - let coord1 = vec![100.0, 0.2]; - let coord2 = vec![101.0, 1.0]; + let coord1 = Position::from([100.0, 0.2]); + let coord2 = Position::from([101.0, 1.0]); let geojson_line_string = Value::LineString(vec![coord1.clone(), coord2.clone()]); use std::convert::TryFrom; let error = geo_types::Point::::try_from(geojson_line_string).unwrap_err(); @@ -678,10 +678,10 @@ mod tests { #[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 coord1 = Position::from([100.0, 0.2]); + let coord2 = Position::from([101.0, 1.0]); + let coord3 = Position::from([102.0, 0.8]); + let coord4 = Position::from([104.0, 0.2]); let geojson_point = Value::Point(coord1.clone()); let _: geo_types::Point = (&geojson_point).try_into()?; diff --git a/src/feature.rs b/src/feature.rs index 9e82e32..b2ee9b5 100644 --- a/src/feature.rs +++ b/src/feature.rs @@ -222,8 +222,7 @@ impl Serialize for Id { #[cfg(test)] mod tests { - use crate::JsonObject; - use crate::{feature, Error, Feature, GeoJson, Geometry, Value}; + use crate::{feature, Error, Feature, GeoJson, Geometry, JsonObject, Position, Value}; use serde_json::json; use std::str::FromStr; @@ -252,7 +251,7 @@ mod tests { } fn value() -> Value { - Value::Point(vec![1.1, 2.1]) + Value::Point(Position::from([1.1, 2.1])) } fn geometry() -> Geometry { @@ -347,7 +346,7 @@ mod tests { let feature_json_str = "{\"geometry\":{\"coordinates\":[1.1,2.1],\"type\":\"Point\"},\"id\":0,\"properties\":{},\"type\":\"Feature\"}"; let feature = crate::Feature { geometry: Some(Geometry { - value: Value::Point(vec![1.1, 2.1]), + value: Value::Point(Position::from([1.1, 2.1])), bbox: None, foreign_members: None, }), @@ -373,7 +372,7 @@ mod tests { let feature_json_str = "{\"geometry\":{\"coordinates\":[1.1,2.1],\"type\":\"Point\"},\"id\":\"foo\",\"properties\":{},\"type\":\"Feature\"}"; let feature = crate::Feature { geometry: Some(Geometry { - value: Value::Point(vec![1.1, 2.1]), + value: Value::Point(Position::from([1.1, 2.1])), bbox: None, foreign_members: None, }), @@ -424,7 +423,7 @@ mod tests { ); let feature = crate::Feature { geometry: Some(Geometry { - value: Value::Point(vec![1.1, 2.1]), + value: Value::Point(Position::from([1.1, 2.1])), bbox: None, foreign_members: None, }), diff --git a/src/feature_collection.rs b/src/feature_collection.rs index ba2c83f..bd2b4d4 100644 --- a/src/feature_collection.rs +++ b/src/feature_collection.rs @@ -51,12 +51,12 @@ use serde_json::json; /// Collect from an iterator: /// /// ```rust -/// use geojson::{Feature, FeatureCollection, Value}; +/// use geojson::{Feature, FeatureCollection, Position, Value}; /// /// let fc: FeatureCollection = (0..10) /// .map(|idx| -> Feature { /// let c = idx as f64; -/// Value::Point(vec![1.0 * c, 2.0 * c, 3.0 * c]).into() +/// Value::Point(Position::from(vec![1.0 * c, 2.0 * c, 3.0 * c])).into() /// }) /// .collect(); /// assert_eq!(fc.features.len(), 10); @@ -253,22 +253,24 @@ impl FromIterator for FeatureCollection { #[cfg(test)] mod tests { - use crate::{Error, Feature, FeatureCollection, Value}; + use crate::{Error, Feature, FeatureCollection, Position, Value}; use serde_json::json; use std::str::FromStr; - #[test] fn test_fc_from_iterator() { let features: Vec = vec![ { - let mut feat: Feature = Value::Point(vec![0., 0., 0.]).into(); + let mut feat: Feature = Value::Point(Position::from(vec![0., 0., 0.])).into(); feat.bbox = Some(vec![-1., -1., -1., 1., 1., 1.]); feat }, { - let mut feat: Feature = - Value::MultiPoint(vec![vec![10., 10., 10.], vec![11., 11., 11.]]).into(); + let mut feat: Feature = Value::MultiPoint(vec![ + Position::from(vec![10., 10., 10.]), + Position::from(vec![11., 11., 11.]), + ]) + .into(); feat.bbox = Some(vec![10., 10., 10., 11., 11., 11.]); feat }, diff --git a/src/feature_iterator.rs b/src/feature_iterator.rs index 9155067..f403b7d 100644 --- a/src/feature_iterator.rs +++ b/src/feature_iterator.rs @@ -129,7 +129,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{Geometry, Value}; + use crate::{Geometry, Position, Value}; use std::io::BufReader; @@ -187,7 +187,7 @@ mod tests { assert_eq!( Geometry { bbox: None, - value: Value::Point(vec![102.0, 0.5]), + value: Value::Point(Position::from([102.0, 0.5])), foreign_members: None, }, fi.next().unwrap().unwrap().geometry.unwrap() @@ -196,10 +196,10 @@ mod tests { Geometry { bbox: None, value: Value::LineString(vec![ - vec![102.0, 0.0], - vec![103.0, 1.0], - vec![104.0, 0.0], - vec![105.0, 1.0] + Position::from([102.0, 0.0]), + Position::from([103.0, 1.0]), + Position::from([104.0, 0.0]), + Position::from([105.0, 1.0]) ]), foreign_members: None, }, @@ -209,11 +209,11 @@ mod tests { Geometry { bbox: None, value: Value::Polygon(vec![vec![ - vec![100.0, 0.0], - vec![101.0, 0.0], - vec![101.0, 1.0], - vec![100.0, 1.0], - vec![100.0, 0.0] + Position::from([100.0, 0.0]), + Position::from([101.0, 0.0]), + Position::from([101.0, 1.0]), + Position::from([100.0, 1.0]), + Position::from([100.0, 0.0]) ]]), foreign_members: None, }, diff --git a/src/feature_writer.rs b/src/feature_writer.rs index a48c578..b3f484b 100644 --- a/src/feature_writer.rs +++ b/src/feature_writer.rs @@ -226,9 +226,10 @@ impl Drop for FeatureWriter { #[cfg(test)] mod tests { use super::*; - use crate::JsonValue; + use crate::{JsonValue, Position}; use serde_json::json; + use tinyvec::tiny_vec; // an example struct that we want to serialize #[derive(Serialize)] @@ -284,7 +285,9 @@ mod tests { Feature { bbox: None, - geometry: Some(crate::Geometry::from(crate::Value::Point(vec![1.1, 1.2]))), + geometry: Some(crate::Geometry::from(crate::Value::Point(Position::from( + [1.1, 1.2], + )))), id: None, properties: Some(props), foreign_members: None, @@ -298,7 +301,9 @@ mod tests { Feature { bbox: None, - geometry: Some(crate::Geometry::from(crate::Value::Point(vec![2.1, 2.2]))), + geometry: Some(crate::Geometry::from(crate::Value::Point(Position::from( + [2.1, 2.2], + )))), id: None, properties: Some(props), foreign_members: None, @@ -340,12 +345,12 @@ mod tests { { let mut writer = FeatureWriter::from_writer(&mut buffer); let record_1 = MyRecord { - geometry: crate::Geometry::from(crate::Value::Point(vec![1.1, 1.2])), + geometry: crate::Geometry::from(crate::Value::Point(Position::from([1.1, 1.2]))), name: "Mishka".to_string(), age: 12, }; let record_2 = MyRecord { - geometry: crate::Geometry::from(crate::Value::Point(vec![2.1, 2.2])), + geometry: crate::Geometry::from(crate::Value::Point(Position::from([2.1, 2.2]))), name: "Jane".to_string(), age: 22, }; diff --git a/src/geojson.rs b/src/geojson.rs index 862e571..2c33541 100644 --- a/src/geojson.rs +++ b/src/geojson.rs @@ -164,7 +164,7 @@ impl GeoJson { /// # Example /// ``` /// use std::convert::TryInto; - /// use geojson::{Feature, GeoJson, Geometry, Value}; + /// use geojson::{Feature, GeoJson, Geometry, Position, Value}; /// use serde_json::json; /// /// let json_value = json!({ @@ -184,7 +184,7 @@ impl GeoJson { /// geojson, /// GeoJson::Feature(Feature { /// bbox: None, - /// geometry: Some(Geometry::new(Value::Point(vec![102.0, 0.5]))), + /// geometry: Some(Geometry::new(Value::Point(Position::from([102.0, 0.5])))), /// id: None, /// properties: None, /// foreign_members: None, @@ -398,10 +398,11 @@ impl fmt::Display for FeatureCollection { #[cfg(test)] mod tests { - use crate::{Error, Feature, FeatureCollection, GeoJson, Geometry, Value}; + use crate::{Error, Feature, FeatureCollection, GeoJson, Geometry, Position, Value}; use serde_json::json; use std::convert::TryInto; use std::str::FromStr; + use tinyvec::tiny_vec; #[test] fn test_geojson_from_reader() { @@ -449,7 +450,7 @@ mod tests { geojson, GeoJson::Feature(Feature { bbox: None, - geometry: Some(Geometry::new(Value::Point(vec![102.0, 0.5]))), + geometry: Some(Geometry::new(Value::Point(Position::from([102.0, 0.5])))), id: None, properties: None, foreign_members: None, @@ -460,8 +461,8 @@ mod tests { #[test] fn test_geojson_from_features() { let features: Vec = vec![ - Value::Point(vec![0., 0., 0.]).into(), - Value::Point(vec![1., 1., 1.]).into(), + Value::Point(Position::from(vec![0., 0., 0.])).into(), + Value::Point(Position::from(vec![1., 1., 1.])).into(), ]; let geojson: GeoJson = features.into(); @@ -471,14 +472,18 @@ mod tests { features: vec![ Feature { bbox: None, - geometry: Some(Geometry::new(Value::Point(vec![0., 0., 0.]))), + geometry: Some(Geometry::new(Value::Point(Position::from(vec![ + 0., 0., 0. + ])))), id: None, properties: None, foreign_members: None, }, Feature { bbox: None, - geometry: Some(Geometry::new(Value::Point(vec![1., 1., 1.]))), + geometry: Some(Geometry::new(Value::Point(Position::from(vec![ + 1., 1., 1. + ])))), id: None, properties: None, foreign_members: None, @@ -507,7 +512,7 @@ mod tests { geojson, GeoJson::Feature(Feature { bbox: None, - geometry: Some(Geometry::new(Value::Point(vec![102.0, 0.5]))), + geometry: Some(Geometry::new(Value::Point(Position::from([102.0, 0.5])))), id: None, properties: None, foreign_members: None, diff --git a/src/geometry.rs b/src/geometry.rs index a150654..97627b1 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -34,11 +34,11 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// let genum = geo_types::Geometry::from(point); /// assert_eq!( /// geojson::Value::from(&point), -/// geojson::Value::Point(vec![2., 9.]), +/// geojson::Value::Point(geojson::Position::from([2., 9.])), /// ); /// assert_eq!( /// geojson::Value::from(&genum), -/// geojson::Value::Point(vec![2., 9.]), +/// geojson::Value::Point(geojson::Position::from([2., 9.])), /// ); /// # } /// # #[cfg(not(feature = "geo-types"))] @@ -186,24 +186,24 @@ impl Serialize for Value { /// Constructing a `Geometry`: /// /// ``` -/// use geojson::{Geometry, Value}; +/// use geojson::{Geometry, Position, Value}; /// -/// let geometry = Geometry::new(Value::Point(vec![7.428959, 1.513394])); +/// let geometry = Geometry::new(Value::Point(Position::from([7.428959, 1.513394]))); /// ``` /// /// Geometries can be created from `Value`s. /// ``` -/// # use geojson::{Geometry, Value}; -/// let geometry1: Geometry = Value::Point(vec![7.428959, 1.513394]).into(); +/// # use geojson::{Geometry, Position, Value}; +/// let geometry1: Geometry = Value::Point(Position::from([7.428959, 1.513394])).into(); /// ``` /// /// Serializing a `Geometry` to a GeoJSON string: /// /// ``` -/// use geojson::{GeoJson, Geometry, Value}; +/// use geojson::{GeoJson, Geometry, Position, Value}; /// use serde_json; /// -/// let geometry = Geometry::new(Value::Point(vec![7.428959, 1.513394])); +/// let geometry = Geometry::new(Value::Point(Position::from([7.428959, 1.513394]))); /// /// let geojson_string = geometry.to_string(); /// @@ -216,7 +216,7 @@ impl Serialize for Value { /// Deserializing a GeoJSON string into a `Geometry`: /// /// ``` -/// use geojson::{GeoJson, Geometry, Value}; +/// use geojson::{GeoJson, Geometry, Position, Value}; /// /// let geojson_str = "{\"coordinates\":[7.428959,1.513394],\"type\":\"Point\"}"; /// @@ -226,7 +226,7 @@ impl Serialize for Value { /// }; /// /// assert_eq!( -/// Geometry::new(Value::Point(vec![7.428959, 1.513394]),), +/// Geometry::new(Value::Point(Position::from([7.428959, 1.513394])),), /// geometry, /// ); /// ``` @@ -235,10 +235,10 @@ impl Serialize for Value { /// feature): /// /// ``` -/// use geojson::{Geometry, Value}; +/// use geojson::{Geometry, Position, Value}; /// use std::convert::TryInto; /// -/// let geometry = Geometry::new(Value::Point(vec![7.428959, 1.513394])); +/// let geometry = Geometry::new(Value::Point(Position::from([7.428959, 1.513394]))); /// # #[cfg(feature = "geo-types")] /// let geom: geo_types::Geometry = geometry.try_into().unwrap(); /// ``` @@ -361,7 +361,7 @@ where #[cfg(test)] mod tests { - use crate::{Error, GeoJson, Geometry, JsonObject, Value}; + use crate::{Error, GeoJson, Geometry, JsonObject, Position, Value}; use serde_json::json; use std::str::FromStr; @@ -376,7 +376,7 @@ mod tests { fn encode_decode_geometry() { let geometry_json_str = "{\"coordinates\":[1.1,2.1],\"type\":\"Point\"}"; let geometry = Geometry { - value: Value::Point(vec![1.1, 2.1]), + value: Value::Point(Position::from([1.1, 2.1])), bbox: None, foreign_members: None, }; @@ -410,7 +410,7 @@ mod tests { assert_eq!( geometry, Geometry { - value: Value::Point(vec![0.0, 0.1]), + value: Value::Point(Position::from([0.0, 0.1])), bbox: None, foreign_members: None, } @@ -419,7 +419,11 @@ mod tests { #[test] fn test_geometry_display() { - let v = Value::LineString(vec![vec![0.0, 0.1], vec![0.1, 0.2], vec![0.2, 0.3]]); + let v = Value::LineString(vec![ + Position::from([0.0, 0.1]), + Position::from([0.1, 0.2]), + Position::from([0.2, 0.3]), + ]); let geometry = Geometry::new(v); assert_eq!( "{\"coordinates\":[[0.0,0.1],[0.1,0.2],[0.2,0.3]],\"type\":\"LineString\"}", @@ -429,7 +433,11 @@ mod tests { #[test] fn test_value_display() { - let v = Value::LineString(vec![vec![0.0, 0.1], vec![0.1, 0.2], vec![0.2, 0.3]]); + let v = Value::LineString(vec![ + Position::from([0.0, 0.1]), + Position::from([0.1, 0.2]), + Position::from([0.2, 0.3]), + ]); assert_eq!( "{\"coordinates\":[[0.0,0.1],[0.1,0.2],[0.2,0.3]],\"type\":\"LineString\"}", v.to_string() @@ -446,7 +454,7 @@ mod tests { serde_json::to_value(true).unwrap(), ); let geometry = Geometry { - value: Value::Point(vec![1.1, 2.1]), + value: Value::Point(Position::from([1.1, 2.1])), bbox: None, foreign_members: Some(foreign_members), }; @@ -470,12 +478,15 @@ mod tests { value: Value::GeometryCollection(vec![ Geometry { bbox: None, - value: Value::Point(vec![100.0, 0.0]), + value: Value::Point(Position::from([100.0, 0.0])), foreign_members: None, }, Geometry { bbox: None, - value: Value::LineString(vec![vec![101.0, 0.0], vec![102.0, 1.0]]), + value: Value::LineString(vec![ + Position::from([101.0, 0.0]), + Position::from([102.0, 1.0]), + ]), foreign_members: None, }, ]), diff --git a/src/lib.rs b/src/lib.rs index 045faa0..e49075e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,7 @@ //! // read geometry data //! let geometry: Geometry = feature.geometry.unwrap(); //! if let Value::Point(coords) = geometry.value { -//! assert_eq!(coords, vec![-118.2836, 34.0956]); +//! assert_eq!(coords.as_slice(), &[-118.2836, 34.0956]); //! } //! //! # else { @@ -111,7 +111,7 @@ //! `GeoJson` can be serialized by calling [`to_string`](geojson/enum.GeoJson.html#impl-ToString): //! //! ```rust -//! use geojson::{Feature, GeoJson, Geometry, Value}; +//! use geojson::{Feature, GeoJson, Geometry, Position, Value}; //! # fn get_properties() -> ::geojson::JsonObject { //! # let mut properties = ::geojson::JsonObject::new(); //! # properties.insert( @@ -122,7 +122,7 @@ //! # } //! # fn main() { //! -//! let geometry = Geometry::new(Value::Point(vec![-120.66029, 35.2812])); +//! let geometry = Geometry::new(Value::Point(Position::from([-120.66029, 35.2812]))); //! //! let geojson = GeoJson::Feature(Feature { //! bbox: None, @@ -259,11 +259,11 @@ //! //! assert_eq!( //! geojson::Value::from(&geo_point), -//! geojson::Value::Point(vec![2., 9.]), +//! geojson::Value::Point(geojson::Position::from([2., 9.])), //! ); //! assert_eq!( //! geojson::Value::from(&geo_geometry), -//! geojson::Value::Point(vec![2., 9.]), +//! geojson::Value::Point(geojson::Position::from([2., 9.])), //! ); //! # } //! ``` @@ -421,10 +421,66 @@ /// [GeoJSON Format Specification § 5](https://tools.ietf.org/html/rfc7946#section-5) pub type Bbox = Vec; +use tinyvec::TinyVec; /// Positions /// /// [GeoJSON Format Specification § 3.1.1](https://tools.ietf.org/html/rfc7946#section-3.1.1) -pub type Position = Vec; +#[derive(Debug, Clone, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)] +pub struct Position(TinyVec<[f64; 2]>); + +impl Position { + pub fn as_slice_mut(&mut self) -> &mut [f64] { + &mut self.0 + } + + pub fn as_slice(&self) -> &[f64] { + &self.0 + } +} + +impl From> for Position { + fn from(value: TinyVec<[f64; 2]>) -> Self { + Self(value) + } +} + +impl From> for Position { + fn from(value: Vec) -> Self { + Self(TinyVec::Heap(value)) + } +} + +impl From<[f64; 2]> for Position { + fn from(value: [f64; 2]) -> Self { + Self(TinyVec::Inline(value.into())) + } +} + +impl From<(f64, f64)> for Position { + fn from(value: (f64, f64)) -> Self { + Self::from([value.0, value.1]) + } +} + +use std::ops::{Index, IndexMut}; +use std::slice::SliceIndex; + +impl> Index for Position { + type Output = >::Output; + #[inline(always)] + #[must_use] + fn index(&self, index: I) -> &Self::Output { + &self.0[index] + } +} + +impl> IndexMut for Position { + #[inline(always)] + #[must_use] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + &mut self.0[index] + } +} pub type PointType = Position; pub type LineStringType = Vec; diff --git a/src/ser.rs b/src/ser.rs index 1a17e5f..e0de23a 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -362,7 +362,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::JsonValue; + use crate::{JsonValue, Position}; use serde_json::json; @@ -377,7 +377,7 @@ mod tests { } let my_feature = { - let geometry = crate::Geometry::new(crate::Value::Point(vec![0.0, 1.0])); + let geometry = crate::Geometry::new(crate::Value::Point(Position::from([0.0, 1.0]))); let name = "burbs".to_string(); MyStruct { geometry, name } }; @@ -409,7 +409,9 @@ mod tests { #[test] fn with_some_geom() { let my_feature = { - let geometry = Some(crate::Geometry::new(crate::Value::Point(vec![0.0, 1.0]))); + let geometry = Some(crate::Geometry::new(crate::Value::Point(Position::from([ + 0.0, 1.0, + ])))); let name = "burbs".to_string(); MyStruct { geometry, name } }; diff --git a/src/util.rs b/src/util.rs index a1e4897..5234f36 100644 --- a/src/util.rs +++ b/src/util.rs @@ -213,11 +213,11 @@ fn json_to_position(json: &JsonValue) -> Result { if coords_array.len() < 2 { return Err(Error::PositionTooShort(coords_array.len())); } - let mut coords = Vec::with_capacity(coords_array.len()); + let mut coords = tinyvec::TinyVec::with_capacity(coords_array.len()); for position in coords_array { coords.push(expect_f64(position)?); } - Ok(coords) + Ok(Position(coords)) } fn json_to_1d_positions(json: &JsonValue) -> Result> {