s2json_core/
lib.rs

1#![no_std]
2#![feature(coverage_attribute)]
3#![deny(missing_docs)]
4
5//! The `s2json` Rust crate provides functionalities to read and write S2JSON Spec data structures.
6//! This crate is a 0 dependency package that uses `no_std` and is intended to be used in
7//! embedded systems and WASM applications.
8//! NOTE: WM stands for WGS84 and S2 stands for S2Geometry
9
10extern crate alloc;
11
12/// All geometry types and structs
13pub mod geometry;
14/// BTreeMap wrapper
15pub mod map;
16/// All values types and structs
17pub mod value;
18/// All values impl
19pub mod value_impl;
20/// The VectorPoint struct is a powerful tool for 2D and 3D points
21pub mod vector_point;
22
23use alloc::{string::String, vec::Vec};
24pub use geometry::*;
25pub use map::*;
26use serde::{Deserialize, Serialize};
27pub use value::*;
28pub use vector_point::*;
29
30/// All projections that can be used
31#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
32pub enum Projection {
33    /// S2
34    #[default]
35    S2,
36    /// WG
37    WG,
38}
39
40//? S2 specific type
41
42/// Cube-face on the S2 sphere
43#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
44pub enum Face {
45    /// Face 0
46    #[default]
47    Face0 = 0,
48    /// Face 1
49    Face1 = 1,
50    /// Face 2
51    Face2 = 2,
52    /// Face 3
53    Face3 = 3,
54    /// Face 4
55    Face4 = 4,
56    /// Face 5
57    Face5 = 5,
58}
59impl From<Face> for u8 {
60    fn from(face: Face) -> Self {
61        face as u8
62    }
63}
64impl From<u8> for Face {
65    fn from(face: u8) -> Self {
66        match face {
67            1 => Face::Face1,
68            2 => Face::Face2,
69            3 => Face::Face3,
70            4 => Face::Face4,
71            5 => Face::Face5,
72            _ => Face::Face0,
73        }
74    }
75}
76impl serde::Serialize for Face {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78    where
79        S: serde::Serializer,
80    {
81        serializer.serialize_u8(*self as u8)
82    }
83}
84
85impl<'de> serde::Deserialize<'de> for Face {
86    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
87    where
88        D: serde::Deserializer<'de>,
89    {
90        let value = u8::deserialize(deserializer)?;
91        match value {
92            0 => Ok(Face::Face0),
93            1 => Ok(Face::Face1),
94            2 => Ok(Face::Face2),
95            3 => Ok(Face::Face3),
96            4 => Ok(Face::Face4),
97            5 => Ok(Face::Face5),
98            _ => Err(serde::de::Error::custom("Invalid face value")),
99        }
100    }
101}
102
103/// FeatureCollection type string
104#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
105pub enum FeatureCollectionType {
106    /// WM FeatureCollection
107    #[default]
108    FeatureCollection,
109}
110impl From<&str> for FeatureCollectionType {
111    fn from(_: &str) -> Self {
112        FeatureCollectionType::FeatureCollection
113    }
114}
115
116/// FeatureCollection type string
117#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
118pub enum S2FeatureCollectionType {
119    /// WM FeatureCollection
120    #[default]
121    S2FeatureCollection,
122}
123impl From<&str> for S2FeatureCollectionType {
124    fn from(_: &str) -> Self {
125        S2FeatureCollectionType::S2FeatureCollection
126    }
127}
128
129//? FeatureCollections
130
131/// WM FeatureCollection
132#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
133pub struct FeatureCollection<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
134    /// Type will always be "FeatureCollection"
135    #[serde(rename = "type")]
136    pub _type: FeatureCollectionType,
137    /// Collection of WM features
138    pub features: Vec<WMFeature<M, P, D>>,
139    /// Attribution data
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub attributions: Option<Attributions>,
142    /// Bounding box
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub bbox: Option<BBox>,
145}
146impl<M, P: Clone + Default, D: Clone + Default> FeatureCollection<M, P, D> {
147    /// Create a new FeatureCollection
148    pub fn new(attributions: Option<Attributions>) -> Self {
149        Self { _type: "FeatureCollection".into(), features: Vec::new(), attributions, bbox: None }
150    }
151
152    /// update the bounding box
153    pub fn update_bbox(&mut self, bbox: BBox) {
154        let mut self_bbox = self.bbox.unwrap_or_default();
155        self_bbox = self_bbox.merge(&bbox);
156        self.bbox = Some(self_bbox);
157    }
158}
159
160/// S2 FeatureCollection
161#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
162pub struct S2FeatureCollection<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue>
163{
164    /// Type will always be "S2FeatureCollection"
165    #[serde(rename = "type")]
166    pub _type: S2FeatureCollectionType,
167    /// Collection of S2 features
168    pub features: Vec<VectorFeature<M, P, D>>,
169    /// Track the faces that were used to generate the features
170    pub faces: Vec<Face>,
171    /// Attribution data
172    #[serde(skip_serializing_if = "Option::is_none")]
173    pub attributions: Option<Attributions>,
174    /// Bounding box
175    #[serde(skip_serializing_if = "Option::is_none")]
176    pub bbox: Option<BBox>,
177}
178impl<M, P: Clone + Default, D: Clone + Default> S2FeatureCollection<M, P, D> {
179    /// Create a new S2FeatureCollection
180    pub fn new(attributions: Option<Attributions>) -> Self {
181        Self {
182            _type: "S2FeatureCollection".into(),
183            features: Vec::new(),
184            faces: Vec::new(),
185            attributions,
186            bbox: None,
187        }
188    }
189
190    /// update the bounding box
191    pub fn update_bbox(&mut self, bbox: BBox) {
192        let mut self_bbox = self.bbox.unwrap_or_default();
193        self_bbox = self_bbox.merge(&bbox);
194        self.bbox = Some(self_bbox);
195    }
196
197    /// Add a face, ensuring it is unique
198    pub fn add_face(&mut self, face: Face) {
199        if !self.faces.contains(&face) {
200            self.faces.push(face);
201        }
202    }
203}
204
205//? Features
206
207/// Feature type string
208#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
209pub enum FeatureType {
210    /// WM Feature
211    #[default]
212    Feature,
213}
214impl From<&str> for FeatureType {
215    fn from(_: &str) -> Self {
216        FeatureType::Feature
217    }
218}
219
220/// Component to build an WM Feature
221#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
222pub struct Feature<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
223    /// Type will always be "Feature"
224    #[serde(rename = "type")]
225    pub _type: FeatureType,
226    /// Unique identifier
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub id: Option<u64>,
229    /// Properties of the feature
230    pub properties: P,
231    /// Geometry of the feature
232    pub geometry: Geometry<D>,
233    /// Metadata of the feature
234    #[serde(skip_serializing_if = "Option::is_none")]
235    pub metadata: Option<M>,
236}
237impl<M, P: Clone + Default, D: Clone + Default> Feature<M, P, D> {
238    /// Create a new Feature
239    pub fn new(id: Option<u64>, properties: P, geometry: Geometry<D>, metadata: Option<M>) -> Self {
240        Self { _type: "Feature".into(), id, properties, geometry, metadata }
241    }
242}
243impl<M, P: Clone + Default, D: Clone + Default> Default for Feature<M, P, D> {
244    fn default() -> Self {
245        Self {
246            _type: "Feature".into(),
247            id: None,
248            properties: Default::default(),
249            geometry: Default::default(),
250            metadata: None,
251        }
252    }
253}
254
255/// Feature type string
256#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
257pub enum VectorFeatureType {
258    /// WM Feature
259    #[default]
260    VectorFeature,
261    /// S2 Feature
262    S2Feature,
263}
264impl From<&str> for VectorFeatureType {
265    fn from(s: &str) -> Self {
266        match s {
267            "S2Feature" => VectorFeatureType::S2Feature,
268            _ => VectorFeatureType::VectorFeature,
269        }
270    }
271}
272
273/// Component to build an WM or S2 Vector Feature
274#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
275pub struct VectorFeature<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
276    /// Type will always be "VectorFeature"
277    #[serde(rename = "type")]
278    pub _type: VectorFeatureType,
279    /// Unique identifier
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub id: Option<u64>,
282    /// Face of the feature
283    pub face: Face,
284    /// Properties of the feature
285    pub properties: P,
286    /// Geometry of the feature
287    pub geometry: VectorGeometry<D>,
288    /// Metadata of the feature
289    #[serde(skip_serializing_if = "Option::is_none")]
290    pub metadata: Option<M>,
291}
292impl<M, P: Clone + Default, D: Clone + Default> Default for VectorFeature<M, P, D> {
293    fn default() -> Self {
294        Self {
295            _type: "VectorFeature".into(),
296            face: 0.into(),
297            id: None,
298            properties: Default::default(),
299            geometry: Default::default(),
300            metadata: None,
301        }
302    }
303}
304impl<M, P: Clone + Default, D: Clone + Default> VectorFeature<M, P, D> {
305    /// Create a new VectorFeature in the WM format
306    pub fn new_wm(
307        id: Option<u64>,
308        properties: P,
309        geometry: VectorGeometry<D>,
310        metadata: Option<M>,
311    ) -> Self {
312        Self { _type: "VectorFeature".into(), face: 0.into(), id, properties, geometry, metadata }
313    }
314
315    /// Create a new VectorFeature in the WM format
316    pub fn new_s2(
317        id: Option<u64>,
318        face: Face,
319        properties: P,
320        geometry: VectorGeometry<D>,
321        metadata: Option<M>,
322    ) -> Self {
323        Self { _type: "S2Feature".into(), face, id, properties, geometry, metadata }
324    }
325
326    /// Create a new VectorFeature using an input VectorFeature. Assign new geometry if provided
327    pub fn from_vector_feature(
328        feature: &VectorFeature<M, P, D>,
329        geometry: Option<VectorGeometry<D>>,
330    ) -> Self
331    where
332        M: Clone,
333    {
334        Self {
335            _type: feature._type.clone(),
336            id: feature.id,
337            face: feature.face,
338            properties: feature.properties.clone(),
339            geometry: geometry.unwrap_or(feature.geometry.clone()),
340            metadata: feature.metadata.clone(),
341        }
342    }
343}
344
345//? Utility types
346
347/// Attribution data is stored in an object.
348/// The key is the name of the attribution, and the value is the href link
349/// e.g. { "Open S2": "https://opens2.com/legal/data" }
350pub type Attributions = Map<String, String>;
351
352/// Either an S2 or WM FeatureCollection
353#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
354pub enum FeatureCollections<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
355    /// An WM FeatureCollection
356    FeatureCollection(FeatureCollection<M, P, D>),
357    /// An S2 FeatureCollection
358    S2FeatureCollection(S2FeatureCollection<M, P, D>),
359}
360
361/// Either an S2 or WM Feature
362#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
363pub enum Features<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
364    /// An WM Feature
365    Feature(Feature<M, P, D>),
366    /// An WM or S2 Vector Feature
367    VectorFeature(VectorFeature<M, P, D>),
368}
369
370/// Either an WM Feature or an WM Vector Feature
371#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
372#[serde(untagged)]
373pub enum WMFeature<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
374    /// An WM Feature
375    Feature(Feature<M, P, D>),
376    /// An WM Vector Feature
377    VectorFeature(VectorFeature<M, P, D>),
378}
379
380/// All major S2JSON types
381#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
382#[serde(untagged)]
383pub enum JSONCollection<M = (), P: Clone + Default = Properties, D: Clone + Default = MValue> {
384    /// An WM FeatureCollection
385    FeatureCollection(FeatureCollection<M, P, D>),
386    /// An S2 FeatureCollection
387    S2FeatureCollection(S2FeatureCollection<M, P, D>),
388    /// An WM Feature
389    Feature(Feature<M, P, D>),
390    /// An WM Vector Feature
391    VectorFeature(VectorFeature<M, P, D>),
392}
393
394#[cfg(test)]
395mod tests {
396    use super::*;
397    use alloc::{string::ToString, vec};
398
399    #[test]
400    fn face() {
401        let face = Face::Face0;
402        assert_eq!(u8::from(face), 0);
403        let face = Face::Face1;
404        assert_eq!(u8::from(face), 1);
405        let face = Face::Face2;
406        assert_eq!(u8::from(face), 2);
407        let face = Face::Face3;
408        assert_eq!(u8::from(face), 3);
409        let face = Face::Face4;
410        assert_eq!(u8::from(face), 4);
411        let face = Face::Face5;
412        assert_eq!(u8::from(face), 5);
413
414        assert_eq!(Face::Face0, Face::from(0));
415        assert_eq!(Face::Face1, Face::from(1));
416        assert_eq!(Face::Face2, Face::from(2));
417        assert_eq!(Face::Face3, Face::from(3));
418        assert_eq!(Face::Face4, Face::from(4));
419        assert_eq!(Face::Face5, Face::from(5));
420    }
421
422    #[test]
423    fn defaults() {
424        let f: Feature = Default::default();
425        assert_eq!(f._type, "Feature".into());
426        assert_eq!(f.id, None);
427        assert_eq!(f.properties, Properties::default());
428        assert_eq!(f.geometry, Geometry::default());
429        assert_eq!(f.metadata, None);
430
431        let f: VectorFeature = Default::default();
432        assert_eq!(f._type, "VectorFeature".into());
433        assert_eq!(f.id, None);
434        assert_eq!(f.face, 0.into());
435        assert_eq!(f.properties, Properties::default());
436        assert_eq!(f.geometry, VectorGeometry::default());
437        assert_eq!(f.metadata, None);
438    }
439
440    #[test]
441    fn feature_collection_new() {
442        let mut attributions = Attributions::new();
443        attributions.insert("Open S2".to_string(), "https://opens2.com/legal/data".to_string());
444        let mut fc = FeatureCollection::<()>::new(Some(attributions.clone()));
445        assert_eq!(fc._type, FeatureCollectionType::FeatureCollection);
446        assert_eq!(fc.features.len(), 0);
447        assert_eq!(fc.attributions, Some(attributions.clone()));
448        // update_bbox
449        fc.update_bbox(BBox::new(5., -2., 35., 2.2));
450        assert_eq!(fc.bbox, Some(BBox::new(5., -2., 35., 2.2)));
451
452        let string = serde_json::to_string(&fc).unwrap();
453        assert_eq!(string, "{\"type\":\"FeatureCollection\",\"features\":[],\"attributions\":{\"Open S2\":\"https://opens2.com/legal/data\"},\"bbox\":[5.0,-2.0,35.0,2.2]}");
454        let back_to_fc: FeatureCollection = serde_json::from_str(&string).unwrap();
455        assert_eq!(back_to_fc, fc);
456    }
457
458    #[test]
459    fn s2_feature_collection_new() {
460        let mut attributions = Attributions::new();
461        attributions.insert("Open S2".to_string(), "https://opens2.com/legal/data".to_string());
462        let mut fc = S2FeatureCollection::new(Some(attributions.clone()));
463        assert_eq!(fc._type, S2FeatureCollectionType::S2FeatureCollection);
464        assert_eq!(fc.features.len(), 0);
465        assert_eq!(fc.attributions, Some(attributions.clone()));
466        // update_bbox
467        fc.update_bbox(BBox::new(5., -2., 35., 2.2));
468        assert_eq!(fc.bbox, Some(BBox::new(5., -2., 35., 2.2)));
469        // add face
470        fc.add_face(0.into());
471        fc.add_face(3.into());
472        assert_eq!(fc.faces, vec![0.into(), 3.into()]);
473
474        let string = serde_json::to_string(&fc).unwrap();
475        assert_eq!(string, "{\"type\":\"S2FeatureCollection\",\"features\":[],\"faces\":[0,3],\"attributions\":{\"Open S2\":\"https://opens2.com/legal/data\"},\"bbox\":[5.0,-2.0,35.0,2.2]}");
476        let back_to_fc: S2FeatureCollection = serde_json::from_str(&string).unwrap();
477        assert_eq!(back_to_fc, fc);
478    }
479
480    #[test]
481    fn feature_new() {
482        let fc: Feature = Feature::new(
483            Some(22),
484            Properties::new(),
485            Geometry::Point(PointGeometry {
486                _type: "Point".into(),
487                coordinates: Point(0.0, 0.0),
488                m_values: None,
489                bbox: None,
490            }),
491            None,
492        );
493        assert_eq!(fc.id, Some(22));
494        assert_eq!(fc._type, "Feature".into());
495        assert_eq!(
496            fc.geometry,
497            Geometry::Point(PointGeometry {
498                _type: "Point".into(),
499                coordinates: Point(0.0, 0.0),
500                m_values: None,
501                bbox: None,
502            })
503        );
504        assert_eq!(fc.properties, Properties::new());
505        assert_eq!(fc.metadata, None);
506    }
507
508    #[test]
509    fn s2_feature_new() {
510        let fc: VectorFeature = VectorFeature::new_wm(
511            Some(55),
512            Properties::new(),
513            VectorGeometry::Point(VectorPointGeometry {
514                _type: "Point".into(),
515                coordinates: VectorPoint { x: 0.0, y: 1.0, z: Some(3.), m: None, t: None },
516                bbox: None,
517                is_3d: true,
518                offset: None,
519                vec_bbox: None,
520                indices: None,
521                tesselation: None,
522            }),
523            None,
524        );
525        assert_eq!(fc.id, Some(55));
526        assert_eq!(fc._type, "VectorFeature".into());
527        assert_eq!(
528            fc.geometry,
529            VectorGeometry::Point(VectorPointGeometry {
530                _type: "Point".into(),
531                coordinates: VectorPoint { x: 0.0, y: 1.0, z: Some(3.), m: None, t: None },
532                bbox: None,
533                is_3d: true,
534                offset: None,
535                vec_bbox: None,
536                indices: None,
537                tesselation: None,
538            })
539        );
540        assert_eq!(fc.properties, Properties::new());
541        assert_eq!(fc.metadata, None);
542        assert_eq!(fc.face, 0.into());
543
544        // S2
545
546        #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
547        struct MetaTest {
548            name: String,
549            value: String,
550        }
551
552        let fc = VectorFeature::<MetaTest>::new_s2(
553            Some(55),
554            3.into(),
555            Properties::new(),
556            VectorGeometry::Point(VectorPointGeometry {
557                _type: "Point".into(),
558                coordinates: VectorPoint { x: 0.0, y: 1.0, z: Some(3.), m: None, t: None },
559                bbox: None,
560                is_3d: true,
561                offset: None,
562                vec_bbox: None,
563                indices: None,
564                tesselation: None,
565            }),
566            Some(MetaTest { name: "test".to_string(), value: "value".to_string() }),
567        );
568        assert_eq!(fc.id, Some(55));
569        assert_eq!(fc._type, "S2Feature".into());
570        assert_eq!(
571            fc.geometry,
572            VectorGeometry::Point(VectorPointGeometry {
573                _type: "Point".into(),
574                coordinates: VectorPoint { x: 0.0, y: 1.0, z: Some(3.), m: None, t: None },
575                bbox: None,
576                is_3d: true,
577                offset: None,
578                vec_bbox: None,
579                indices: None,
580                tesselation: None,
581            })
582        );
583        assert_eq!(fc.properties, Properties::new());
584        assert_eq!(
585            fc.metadata,
586            Some(MetaTest { name: "test".to_string(), value: "value".to_string() })
587        );
588        assert_eq!(fc.face, 3.into());
589
590        let fc_to_str = serde_json::to_string(&fc).unwrap();
591        assert_eq!(
592            fc_to_str,
593            "{\"type\":\"S2Feature\",\"id\":55,\"face\":3,\"properties\":{},\"geometry\":{\"type\"\
594             :\"Point\",\"is3D\":true,\"coordinates\":{\"x\":0.0,\"y\":1.0,\"z\":3.0},\"indices\":\
595             null,\"tesselation\":null},\"metadata\":{\"name\":\"test\",\"value\":\"value\"}}"
596        );
597
598        // from_vector_feature
599
600        let new_geo = VectorGeometry::Point(VectorPointGeometry {
601            _type: "Point".into(),
602            coordinates: VectorPoint { x: 5.0, y: 4.0, z: Some(-3.), m: None, t: None },
603            bbox: None,
604            is_3d: true,
605            offset: None,
606            vec_bbox: None,
607            indices: None,
608            tesselation: None,
609        });
610        let fc_clone_new_geometry =
611            VectorFeature::<MetaTest>::from_vector_feature(&fc, Some(new_geo.clone()));
612
613        assert_eq!(fc_clone_new_geometry.geometry, new_geo);
614    }
615
616    #[test]
617    fn parse_feature_multipoint() {
618        let json_string = r#"{
619            "type": "Feature",
620            "properties": {},
621            "geometry": {
622                "type": "MultiPoint",
623                "coordinates": [
624                    [-13.292352825505162, 54.34883408204476],
625                    [36.83102287804303, 59.56941785818924],
626                    [50.34083898563978, 16.040052775278994],
627                    [76.38149901912357, 35.155968522292056]
628                ]
629            }
630        }"#;
631
632        let feature: Feature = serde_json::from_str(json_string).unwrap();
633        assert_eq!(feature._type, "Feature".into());
634        assert_eq!(
635            feature.geometry,
636            Geometry::MultiPoint(MultiPointGeometry {
637                _type: "MultiPoint".into(),
638                coordinates: vec![
639                    Point(-13.292352825505162, 54.34883408204476),
640                    Point(36.83102287804303, 59.56941785818924),
641                    Point(50.34083898563978, 16.040052775278994),
642                    Point(76.38149901912357, 35.155968522292056),
643                ],
644                ..Default::default()
645            })
646        );
647
648        let back_to_str = serde_json::to_string(&feature).unwrap();
649        assert_eq!(
650            back_to_str,
651            "{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"MultiPoint\",\"\
652             coordinates\":[[-13.292352825505162,54.34883408204476],[36.83102287804303,59.\
653             56941785818924],[50.34083898563978,16.040052775278994],[76.38149901912357,35.\
654             155968522292056]]}}"
655        );
656    }
657
658    #[test]
659    fn parse_feature_linestring() {
660        let json_string = r#"{
661            "type": "Feature",
662            "properties": {},
663            "geometry": {
664                "type": "LineString",
665                "coordinates": [
666                    [-13.292352825505162, 54.34883408204476],
667                    [36.83102287804303, 59.56941785818924],
668                    [50.34083898563978, 16.040052775278994],
669                    [76.38149901912357, 35.155968522292056]
670                ]
671            }
672        }"#;
673
674        let feature: Feature = serde_json::from_str(json_string).unwrap();
675        assert_eq!(feature._type, "Feature".into());
676        assert_eq!(
677            feature.geometry,
678            Geometry::LineString(LineStringGeometry {
679                _type: "LineString".into(),
680                coordinates: vec![
681                    Point(-13.292352825505162, 54.34883408204476),
682                    Point(36.83102287804303, 59.56941785818924),
683                    Point(50.34083898563978, 16.040052775278994),
684                    Point(76.38149901912357, 35.155968522292056),
685                ],
686                ..Default::default()
687            })
688        );
689
690        let back_to_str = serde_json::to_string(&feature).unwrap();
691        assert_eq!(
692            back_to_str,
693            "{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"LineString\",\"\
694             coordinates\":[[-13.292352825505162,54.34883408204476],[36.83102287804303,59.\
695             56941785818924],[50.34083898563978,16.040052775278994],[76.38149901912357,35.\
696             155968522292056]]}}"
697        );
698    }
699
700    #[test]
701    fn parse_vector_feature_linestring() {
702        let json_string = r#"{
703            "type": "VectorFeature",
704            "face": 0,
705            "properties": {},
706            "geometry": {
707                "type": "LineString",
708                "is3D": false,
709                "coordinates": [
710                    { "x": -13.292352825505162, "y": 54.34883408204476 },
711                    { "x": 36.83102287804303, "y": 59.56941785818924 },
712                    { "x": 50.34083898563978, "y": 16.040052775278994 },
713                    { "x": 76.38149901912357, "y": 35.155968522292056 }
714                ]
715            }
716        }"#;
717
718        let feature: VectorFeature = serde_json::from_str(json_string).unwrap();
719        assert_eq!(feature._type, "VectorFeature".into());
720        let geometry = feature.geometry;
721        assert_eq!(
722            geometry,
723            VectorGeometry::LineString(VectorLineStringGeometry {
724                _type: VectorGeometryType::LineString,
725                is_3d: false,
726                coordinates: vec![
727                    VectorPoint::from_xy(-13.292352825505162, 54.34883408204476),
728                    VectorPoint::from_xy(36.83102287804303, 59.56941785818924),
729                    VectorPoint::from_xy(50.34083898563978, 16.040052775278994),
730                    VectorPoint::from_xy(76.38149901912357, 35.155968522292056),
731                ],
732                ..Default::default()
733            })
734        )
735    }
736
737    #[test]
738    fn parse_vector_feature_multipoint() {
739        let json_string = r#"{
740            "type": "VectorFeature",
741            "face": 0,
742            "properties": {},
743            "geometry": {
744                "type": "MultiPoint",
745                "is3D": false,
746                "coordinates": [
747                    { "x": -13.292352825505162, "y": 54.34883408204476 },
748                    { "x": 36.83102287804303, "y": 59.56941785818924 },
749                    { "x": 50.34083898563978, "y": 16.040052775278994 },
750                    { "x": 76.38149901912357, "y": 35.155968522292056 }
751                ]
752            }
753        }"#;
754
755        let feature: VectorFeature = serde_json::from_str(json_string).unwrap();
756        assert_eq!(feature._type, "VectorFeature".into());
757        let geometry = feature.geometry;
758        assert_eq!(
759            geometry,
760            VectorGeometry::MultiPoint(VectorMultiPointGeometry {
761                _type: VectorGeometryType::MultiPoint,
762                is_3d: false,
763                coordinates: vec![
764                    VectorPoint::from_xy(-13.292352825505162, 54.34883408204476),
765                    VectorPoint::from_xy(36.83102287804303, 59.56941785818924),
766                    VectorPoint::from_xy(50.34083898563978, 16.040052775278994),
767                    VectorPoint::from_xy(76.38149901912357, 35.155968522292056),
768                ],
769                ..Default::default()
770            })
771        )
772    }
773
774    #[test]
775    fn serde_face() {
776        let face_0 = Face::Face0;
777        let serialized = serde_json::to_string(&face_0).unwrap();
778        assert_eq!(serialized, "0");
779        let deserialize = serde_json::from_str::<Face>(&serialized).unwrap();
780        assert_eq!(deserialize, Face::Face0);
781
782        let face_1 = Face::Face1;
783        let serialized = serde_json::to_string(&face_1).unwrap();
784        assert_eq!(serialized, "1");
785        let deserialize = serde_json::from_str::<Face>(&serialized).unwrap();
786        assert_eq!(deserialize, Face::Face1);
787
788        let face_2 = Face::Face2;
789        let serialized = serde_json::to_string(&face_2).unwrap();
790        assert_eq!(serialized, "2");
791        let deserialize = serde_json::from_str::<Face>(&serialized).unwrap();
792        assert_eq!(deserialize, Face::Face2);
793
794        let face_3 = Face::Face3;
795        let serialized = serde_json::to_string(&face_3).unwrap();
796        assert_eq!(serialized, "3");
797        let deserialize = serde_json::from_str::<Face>(&serialized).unwrap();
798        assert_eq!(deserialize, Face::Face3);
799
800        let face_4 = Face::Face4;
801        let serialized = serde_json::to_string(&face_4).unwrap();
802        assert_eq!(serialized, "4");
803        let deserialize = serde_json::from_str::<Face>(&serialized).unwrap();
804        assert_eq!(deserialize, Face::Face4);
805
806        let face_5 = Face::Face5;
807        let serialized = serde_json::to_string(&face_5).unwrap();
808        assert_eq!(serialized, "5");
809        let deserialize = serde_json::from_str::<Face>(&serialized).unwrap();
810        assert_eq!(deserialize, Face::Face5);
811    }
812
813    #[test]
814    #[should_panic(expected = "Invalid face value")]
815    fn serde_face_err() {
816        let _ = serde_json::from_str::<Face>("6").unwrap();
817    }
818}