1use std::{fmt::Display, str::FromStr};
18
19use geo_traits::{Dimensions, GeometryTrait};
20use serde::{Deserialize, Serialize};
21use serde_with::{DeserializeFromStr, SerializeDisplay};
22
23use crate::error::SedonaGeometryError;
24
25#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Clone, Copy)]
34pub enum GeometryTypeId {
35 Geometry,
37 Point,
39 LineString,
41 Polygon,
43 MultiPoint,
45 MultiLineString,
47 MultiPolygon,
49 GeometryCollection,
51}
52
53impl GeometryTypeId {
54 pub fn try_from_wkb_id(wkb_id: u32) -> Result<Self, SedonaGeometryError> {
59 match wkb_id {
60 0 => Ok(Self::Geometry),
61 1 => Ok(Self::Point),
62 2 => Ok(Self::LineString),
63 3 => Ok(Self::Polygon),
64 4 => Ok(Self::MultiPoint),
65 5 => Ok(Self::MultiLineString),
66 6 => Ok(Self::MultiPolygon),
67 7 => Ok(Self::GeometryCollection),
68 _ => Err(SedonaGeometryError::Invalid(format!(
69 "Unknown geometry type identifier {wkb_id}"
70 ))),
71 }
72 }
73
74 pub fn wkb_id(&self) -> u32 {
78 match self {
79 Self::Geometry => 0,
80 Self::Point => 1,
81 Self::LineString => 2,
82 Self::Polygon => 3,
83 Self::MultiPoint => 4,
84 Self::MultiLineString => 5,
85 Self::MultiPolygon => 6,
86 Self::GeometryCollection => 7,
87 }
88 }
89
90 pub fn geojson_id(&self) -> &'static str {
95 match self {
96 Self::Geometry => "Geometry",
97 Self::Point => "Point",
98 Self::LineString => "LineString",
99 Self::Polygon => "Polygon",
100 Self::MultiPoint => "MultiPoint",
101 Self::MultiLineString => "MultiLineString",
102 Self::MultiPolygon => "MultiPolygon",
103 Self::GeometryCollection => "GeometryCollection",
104 }
105 }
106}
107
108impl FromStr for GeometryTypeId {
109 type Err = SedonaGeometryError;
110
111 fn from_str(value: &str) -> Result<Self, Self::Err> {
112 let value_lower = value.to_ascii_lowercase();
113 match value_lower.as_str() {
114 "geometry" => Ok(Self::Geometry),
115 "point" => Ok(Self::Point),
116 "linestring" => Ok(Self::LineString),
117 "polygon" => Ok(Self::Polygon),
118 "multipoint" => Ok(Self::MultiPoint),
119 "multilinestring" => Ok(Self::MultiLineString),
120 "multipolygon" => Ok(Self::MultiPolygon),
121 "geometrycollection" => Ok(Self::GeometryCollection),
122 _ => Err(SedonaGeometryError::Invalid(format!(
123 "Invalid geometry type string: '{value}'"
124 ))),
125 }
126 }
127}
128
129#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, SerializeDisplay, DeserializeFromStr)]
136pub struct GeometryTypeAndDimensions {
137 geometry_type: GeometryTypeId,
138 dimensions: Dimensions,
139}
140
141impl GeometryTypeAndDimensions {
142 pub fn new(geometry_type: GeometryTypeId, dimensions: Dimensions) -> Self {
144 Self {
145 geometry_type,
146 dimensions,
147 }
148 }
149
150 pub fn try_from_geom(geom: &impl GeometryTrait) -> Result<Self, SedonaGeometryError> {
152 let dimensions = geom.dim();
153 let geometry_type = match geom.as_type() {
154 geo_traits::GeometryType::Point(_) => GeometryTypeId::Point,
155 geo_traits::GeometryType::LineString(_) => GeometryTypeId::LineString,
156 geo_traits::GeometryType::Polygon(_) => GeometryTypeId::Polygon,
157 geo_traits::GeometryType::MultiPoint(_) => GeometryTypeId::MultiPoint,
158 geo_traits::GeometryType::MultiLineString(_) => GeometryTypeId::MultiLineString,
159 geo_traits::GeometryType::MultiPolygon(_) => GeometryTypeId::MultiPolygon,
160 geo_traits::GeometryType::GeometryCollection(_) => GeometryTypeId::GeometryCollection,
161 _ => {
162 return Err(SedonaGeometryError::Invalid(
163 "Unsupported geometry type".to_string(),
164 ))
165 }
166 };
167
168 Ok(Self::new(geometry_type, dimensions))
169 }
170
171 pub fn geometry_type(&self) -> GeometryTypeId {
173 self.geometry_type
174 }
175
176 pub fn dimensions(&self) -> Dimensions {
178 self.dimensions
179 }
180
181 pub fn try_from_wkb_id(wkb_id: u32) -> Result<Self, SedonaGeometryError> {
183 let dimensions = match wkb_id / 1000 {
184 0 => Dimensions::Xy,
185 1 => Dimensions::Xyz,
186 2 => Dimensions::Xym,
187 3 => Dimensions::Xyzm,
188 _ => {
189 return Err(SedonaGeometryError::Invalid(format!(
190 "Unknown dimensions in ISO WKB geometry type: {wkb_id}"
191 )))
192 }
193 };
194
195 let geometry_type = GeometryTypeId::try_from_wkb_id(wkb_id % 1000)?;
196 Ok(Self {
197 geometry_type,
198 dimensions,
199 })
200 }
201
202 pub fn wkb_id(&self) -> u32 {
204 let dimensions_id = match self.dimensions {
205 Dimensions::Xy => 0,
206 Dimensions::Xyz => 1000,
207 Dimensions::Xym => 2000,
208 Dimensions::Xyzm => 3000,
209 Dimensions::Unknown(n) => match n {
210 2 => 0,
211 3 => 1000,
212 4 => 3000,
213 _ => {
214 debug_assert!(false, "Unknown dimensions in GeometryTypeAndDimensions");
216 0
217 }
218 },
219 };
220
221 dimensions_id + self.geometry_type.wkb_id()
222 }
223
224 pub fn geojson_id(&self) -> String {
226 self.to_string()
227 }
228}
229
230impl From<(GeometryTypeId, Dimensions)> for GeometryTypeAndDimensions {
231 fn from(value: (GeometryTypeId, Dimensions)) -> Self {
232 Self {
233 geometry_type: value.0,
234 dimensions: value.1,
235 }
236 }
237}
238
239impl Display for GeometryTypeAndDimensions {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 let suffix = match self.dimensions {
242 Dimensions::Xy => "",
243 Dimensions::Xyz => " Z",
244 Dimensions::Xym => " M",
245 Dimensions::Xyzm => " ZM",
246 Dimensions::Unknown(_) => " Unknown",
247 };
248
249 f.write_str(self.geometry_type.geojson_id())?;
250 f.write_str(suffix)
251 }
252}
253
254impl FromStr for GeometryTypeAndDimensions {
255 type Err = SedonaGeometryError;
256
257 fn from_str(value: &str) -> Result<Self, Self::Err> {
258 let mut parts = value.split_ascii_whitespace();
259 let geometry_type = match parts.next() {
260 Some(maybe_geometry_type) => GeometryTypeId::from_str(maybe_geometry_type)?,
261 None => {
262 return Err(SedonaGeometryError::Invalid(format!(
263 "Invalid geometry type string: '{value}'"
264 )))
265 }
266 };
267
268 let dimensions = match parts.next() {
269 Some(maybe_dimensions) => match maybe_dimensions {
270 "z" | "Z" => Dimensions::Xyz,
271 "m" | "M" => Dimensions::Xym,
272 "zm" | "ZM" => Dimensions::Xyzm,
273 _ => {
274 return Err(SedonaGeometryError::Invalid(format!(
275 "invalid geometry type string: '{value}'"
276 )))
277 }
278 },
279 None => Dimensions::Xy,
280 };
281
282 if parts.next().is_some() {
283 return Err(SedonaGeometryError::Invalid(format!(
284 "invalid geometry type string: '{value}'"
285 )));
286 }
287
288 Ok(Self {
289 geometry_type,
290 dimensions,
291 })
292 }
293}
294
295#[derive(Clone, Debug, Default, PartialEq, Eq)]
305pub struct GeometryTypeAndDimensionsSet {
306 types: u32,
315}
316
317impl GeometryTypeAndDimensionsSet {
318 #[inline]
319 pub fn new() -> Self {
320 Self { types: 0 }
321 }
322
323 #[inline]
329 pub fn insert(
330 &mut self,
331 type_and_dim: &GeometryTypeAndDimensions,
332 ) -> Result<(), SedonaGeometryError> {
333 if let Dimensions::Unknown(n) = type_and_dim.dimensions() {
334 return Err(SedonaGeometryError::Invalid(format!(
335 "Unknown dimensions {n} in GeometryTypeAndDimensionsSet::insert"
336 )));
337 }
338 self.insert_or_ignore(type_and_dim);
339 Ok(())
340 }
341
342 #[inline]
349 pub fn insert_or_ignore(&mut self, type_and_dim: &GeometryTypeAndDimensions) {
350 let geom_shift = type_and_dim.geometry_type().wkb_id();
351 if geom_shift >= 8 {
353 panic!(
354 "Invalid geometry type wkb_id {geom_shift} in GeometryTypeAndDimensionsSet::insert_or_ignore"
355 );
356 }
357 let dim_shift = match type_and_dim.dimensions() {
358 geo_traits::Dimensions::Unknown(_) => {
359 return;
361 }
362 geo_traits::Dimensions::Xy => 0,
363 geo_traits::Dimensions::Xyz => 8,
364 geo_traits::Dimensions::Xym => 16,
365 geo_traits::Dimensions::Xyzm => 24,
366 };
367 let bit_position = geom_shift + dim_shift;
368 self.types |= 1 << bit_position;
369 }
370
371 #[inline]
373 pub fn merge(&mut self, other: &Self) {
374 self.types |= other.types;
375 }
376
377 #[inline]
379 pub fn is_empty(&self) -> bool {
380 self.types == 0
381 }
382
383 #[inline]
385 pub fn size(&self) -> usize {
386 self.types.count_ones() as usize
387 }
388
389 #[inline]
391 pub fn clear(&mut self) {
392 self.types = 0;
393 }
394
395 pub fn iter(&self) -> GeometryTypeSetIter {
397 GeometryTypeSetIter {
398 types: self.types,
399 current_bit: 0,
400 }
401 }
402}
403
404pub struct GeometryTypeSetIter {
406 types: u32,
407 current_bit: u32,
408}
409
410impl Iterator for GeometryTypeSetIter {
411 type Item = GeometryTypeAndDimensions;
412
413 fn next(&mut self) -> Option<Self::Item> {
414 while self.current_bit < 32 {
416 let bit = self.current_bit;
417 self.current_bit += 1;
418
419 if (self.types & (1 << bit)) != 0 {
420 let dim_shift = (bit / 8) * 8;
422 let geom_shift = bit % 8;
423 let dimensions = match dim_shift {
424 0 => Dimensions::Xy,
425 8 => Dimensions::Xyz,
426 16 => Dimensions::Xym,
427 24 => Dimensions::Xyzm,
428 _ => panic!(
429 "Invalid dimension bits at position {bit} in GeometryTypeAndDimensionsSet"
430 ),
431 };
432
433 let geometry_type = GeometryTypeId::try_from_wkb_id(geom_shift)
434 .expect("Invalid geometry type wkb_id in GeometryTypeAndDimensionsSet");
435
436 return Some(GeometryTypeAndDimensions::new(geometry_type, dimensions));
437 }
438 }
439
440 None
441 }
442}
443
444impl IntoIterator for &GeometryTypeAndDimensionsSet {
445 type Item = GeometryTypeAndDimensions;
446 type IntoIter = GeometryTypeSetIter;
447
448 fn into_iter(self) -> Self::IntoIter {
449 self.iter()
450 }
451}
452
453impl Serialize for GeometryTypeAndDimensionsSet {
455 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
456 where
457 S: serde::Serializer,
458 {
459 use serde::ser::SerializeSeq; let mut seq = serializer.serialize_seq(Some(self.size()))?;
461 for item in self.iter() {
462 seq.serialize_element(&item)?;
463 }
464 seq.end()
465 }
466}
467
468impl<'de> Deserialize<'de> for GeometryTypeAndDimensionsSet {
470 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
471 where
472 D: serde::Deserializer<'de>,
473 {
474 use serde::de::Error;
475 let items: Vec<GeometryTypeAndDimensions> = Vec::deserialize(deserializer)?;
476 let mut set = GeometryTypeAndDimensionsSet::new();
477 for item in items {
478 set.insert(&item).map_err(D::Error::custom)?;
479 }
480 Ok(set)
481 }
482}
483
484#[cfg(test)]
485mod test {
486 use super::*;
487
488 use rstest::rstest;
489 use Dimensions::*;
490 use GeometryTypeId::*;
491
492 #[rstest]
493 fn geometry_type_wkb_id_roundtrip(
494 #[values(
495 (Geometry, 0),
496 (Point, 1),
497 (LineString, 2),
498 (Polygon, 3),
499 (MultiPoint, 4),
500 (MultiLineString, 5),
501 (MultiPolygon, 6),
502 (GeometryCollection, 7)
503 )]
504 geometry_type_and_id: (GeometryTypeId, u32),
505 ) {
506 let (geometry_type, wkb_id) = geometry_type_and_id;
507 assert_eq!(geometry_type.wkb_id(), wkb_id);
508 assert_eq!(
509 GeometryTypeId::try_from_wkb_id(wkb_id).unwrap(),
510 geometry_type
511 );
512 }
513
514 #[test]
515 fn geometry_type_wkb_id_err() {
516 let err = GeometryTypeId::try_from_wkb_id(17).unwrap_err();
517 assert_eq!(err.to_string(), "Unknown geometry type identifier 17");
518 }
519
520 #[rstest]
521 fn geometry_type_str_roundtrip(
522 #[values(
523 (Geometry, "Geometry"),
524 (Point, "Point"),
525 (LineString, "LineString"),
526 (Polygon, "Polygon"),
527 (MultiPoint, "MultiPoint"),
528 (MultiLineString, "MultiLineString"),
529 (MultiPolygon, "MultiPolygon"),
530 (GeometryCollection, "GeometryCollection")
531 )]
532 geometry_type_and_str: (GeometryTypeId, &str),
533 ) {
534 let (geometry_type, string) = geometry_type_and_str;
535 assert_eq!(geometry_type.geojson_id(), string);
536 assert_eq!(GeometryTypeId::from_str(string).unwrap(), geometry_type);
537 }
538
539 #[test]
540 fn geometry_type_str_err() {
541 let err = GeometryTypeId::from_str("gazornenplat").unwrap_err();
542 assert_eq!(
543 err.to_string(),
544 "Invalid geometry type string: 'gazornenplat'"
545 );
546 }
547
548 #[rstest]
549 fn geometry_type_dims_wkb_id_roundtrip(
550 #[values(
551 (Geometry, 0),
552 (Point, 1),
553 (LineString, 2),
554 (Polygon, 3),
555 (MultiPoint, 4),
556 (MultiLineString, 5),
557 (MultiPolygon, 6),
558 (GeometryCollection, 7)
559 )]
560 geometry_type_and_id: (GeometryTypeId, u32),
561 #[values(
562 (Xy, 0),
563 (Xyz, 1000),
564 (Xym, 2000),
565 (Xyzm, 3000),
566 )]
567 dimensions_and_id: (Dimensions, u32),
568 ) {
569 let (geometry_type, geometry_type_id) = geometry_type_and_id;
570 let (dimensions, dimensions_id) = dimensions_and_id;
571
572 let value = GeometryTypeAndDimensions::new(geometry_type, dimensions);
573 assert_eq!(value.wkb_id(), dimensions_id + geometry_type_id);
574 assert_eq!(
575 GeometryTypeAndDimensions::try_from_wkb_id(dimensions_id + geometry_type_id).unwrap(),
576 value
577 );
578 }
579
580 #[test]
581 fn geometry_type_dims_wkb_id_err() {
582 let err = GeometryTypeAndDimensions::try_from_wkb_id(17).unwrap_err();
583 assert_eq!(err.to_string(), "Unknown geometry type identifier 17");
584
585 let err = GeometryTypeAndDimensions::try_from_wkb_id(4000).unwrap_err();
586 assert_eq!(
587 err.to_string(),
588 "Unknown dimensions in ISO WKB geometry type: 4000"
589 );
590 }
591
592 #[rstest]
593 fn geometry_type_dims_str_roundtrip(
594 #[values(
595 (Geometry, "Geometry"),
596 (Point, "Point"),
597 (LineString, "LineString"),
598 (Polygon, "Polygon"),
599 (MultiPoint, "MultiPoint"),
600 (MultiLineString, "MultiLineString"),
601 (MultiPolygon, "MultiPolygon"),
602 (GeometryCollection, "GeometryCollection")
603 )]
604 geometry_type_and_str: (GeometryTypeId, &str),
605 #[values(
606 (Xy, ""),
607 (Xyz, " Z"),
608 (Xym, " M"),
609 (Xyzm, " ZM"),
610 )]
611 dimensions_and_suffix: (Dimensions, &str),
612 ) {
613 let (geometry_type, geometry_type_id) = geometry_type_and_str;
614 let (dimensions, dimensions_id) = dimensions_and_suffix;
615 let string_id = geometry_type_id.to_string() + dimensions_id;
616
617 let value = GeometryTypeAndDimensions::new(geometry_type, dimensions);
618 assert_eq!(value.geojson_id(), string_id);
619 assert_eq!(
620 GeometryTypeAndDimensions::from_str(string_id.as_str()).unwrap(),
621 value
622 );
623 }
624
625 #[test]
626 fn geometry_type_set_new_is_empty() {
627 let set = GeometryTypeAndDimensionsSet::new();
628 assert!(set.is_empty());
629 assert_eq!(set.size(), 0);
630 assert_eq!(set.iter().count(), 0);
631 }
632
633 #[test]
634 fn geometry_type_set_insert_single() {
635 let mut set = GeometryTypeAndDimensionsSet::new();
636 let point_xy = GeometryTypeAndDimensions::new(Point, Xy);
637
638 set.insert(&point_xy).unwrap();
639 assert!(!set.is_empty());
640 assert_eq!(set.size(), 1);
641
642 let items: Vec<_> = set.iter().collect();
643 assert_eq!(items.len(), 1);
644 assert_eq!(items[0], point_xy);
645 }
646
647 #[test]
648 fn geometry_type_set_insert_duplicate() {
649 let mut set = GeometryTypeAndDimensionsSet::new();
650 let point_xy = GeometryTypeAndDimensions::new(Point, Xy);
651
652 set.insert(&point_xy).unwrap();
653 set.insert(&point_xy).unwrap();
654 set.insert(&point_xy).unwrap();
655
656 assert_eq!(set.size(), 1);
657 let items: Vec<_> = set.iter().collect();
658 assert_eq!(items.len(), 1);
659 assert_eq!(items[0], point_xy);
660 }
661
662 #[test]
663 fn geometry_type_set_insert_all_types() {
664 let mut set = GeometryTypeAndDimensionsSet::new();
665
666 for geom_type in [
668 Geometry,
669 Point,
670 LineString,
671 Polygon,
672 MultiPoint,
673 MultiLineString,
674 MultiPolygon,
675 GeometryCollection,
676 ] {
677 set.insert(&GeometryTypeAndDimensions::new(geom_type, Xy))
678 .unwrap();
679 }
680
681 assert_eq!(set.size(), 8);
682 let items: Vec<_> = set.iter().collect();
683 assert_eq!(items.len(), 8);
684 }
685
686 #[test]
687 fn geometry_type_set_insert_unknown_dimension() {
688 let mut set = GeometryTypeAndDimensionsSet::new();
689 let point_unknown = GeometryTypeAndDimensions::new(Point, Dimensions::Unknown(2));
690
691 let result = set.insert(&point_unknown);
692
693 assert!(result.is_err());
695 assert_eq!(
696 result.unwrap_err().to_string(),
697 "Unknown dimensions 2 in GeometryTypeAndDimensionsSet::insert"
698 );
699 assert!(set.is_empty());
700 }
701
702 #[test]
703 fn geometry_type_set_clear() {
704 let mut set = GeometryTypeAndDimensionsSet::new();
705 let point_xy = GeometryTypeAndDimensions::new(Point, Xy);
706 let linestring_xyz = GeometryTypeAndDimensions::new(LineString, Xyz);
707
708 set.insert(&point_xy).unwrap();
709 set.insert(&linestring_xyz).unwrap();
710 assert!(!set.is_empty());
711 assert_eq!(set.size(), 2);
712
713 set.clear();
714 assert!(set.is_empty());
715 assert_eq!(set.size(), 0);
716 assert_eq!(set.iter().count(), 0);
717 }
718
719 #[test]
720 fn geometry_type_set_merge() {
721 let mut set1 = GeometryTypeAndDimensionsSet::new();
722 let mut set2 = GeometryTypeAndDimensionsSet::new();
723
724 let point_xy = GeometryTypeAndDimensions::new(Point, Xy);
725 let linestring_xy = GeometryTypeAndDimensions::new(LineString, Xy);
726 let polygon_xyz = GeometryTypeAndDimensions::new(Polygon, Xyz);
727
728 set1.insert(&point_xy).unwrap();
729 set1.insert(&linestring_xy).unwrap();
730
731 set2.insert(&linestring_xy).unwrap(); set2.insert(&polygon_xyz).unwrap();
733
734 set1.merge(&set2);
735
736 assert_eq!(set1.size(), 3);
737 let items: Vec<_> = set1.iter().collect();
738 assert_eq!(items.len(), 3);
739 assert!(items.contains(&point_xy));
740 assert!(items.contains(&linestring_xy));
741 assert!(items.contains(&polygon_xyz));
742 }
743
744 #[test]
745 fn geometry_type_set_comprehensive() {
746 let mut set = GeometryTypeAndDimensionsSet::new();
747
748 let test_types = vec![
750 GeometryTypeAndDimensions::new(Geometry, Xy),
751 GeometryTypeAndDimensions::new(Point, Xy),
752 GeometryTypeAndDimensions::new(LineString, Xyz),
753 GeometryTypeAndDimensions::new(Polygon, Xym),
754 GeometryTypeAndDimensions::new(MultiPoint, Xyzm),
755 GeometryTypeAndDimensions::new(MultiLineString, Xy),
756 GeometryTypeAndDimensions::new(MultiPolygon, Xyz),
757 GeometryTypeAndDimensions::new(GeometryCollection, Xym),
758 GeometryTypeAndDimensions::new(GeometryCollection, Xyzm),
759 ];
760
761 for type_and_dim in &test_types {
762 set.insert(type_and_dim).unwrap();
763 }
764
765 assert_eq!(set.size(), test_types.len());
766 let items: Vec<_> = set.iter().collect();
767 assert_eq!(items.len(), test_types.len());
768
769 for type_and_dim in &test_types {
770 assert!(items.contains(type_and_dim));
771 }
772 }
773
774 #[test]
775 fn geometry_type_set_serde_empty() {
776 let set = GeometryTypeAndDimensionsSet::new();
777
778 let json = serde_json::to_string(&set).unwrap();
780 assert_eq!(json, "[]");
781
782 let deserialized: GeometryTypeAndDimensionsSet = serde_json::from_str(&json).unwrap();
784 assert!(deserialized.is_empty());
785 assert_eq!(deserialized.size(), 0);
786 }
787
788 #[test]
789 fn geometry_type_set_serde_single() {
790 let mut set = GeometryTypeAndDimensionsSet::new();
791 let point_xy = GeometryTypeAndDimensions::new(Point, Xy);
792 set.insert(&point_xy).unwrap();
793
794 let json = serde_json::to_string(&set).unwrap();
796 assert_eq!(json, "[\"Point\"]");
797
798 let deserialized: GeometryTypeAndDimensionsSet = serde_json::from_str(&json).unwrap();
800 assert_eq!(deserialized.size(), 1);
801 let items: Vec<_> = deserialized.iter().collect();
802 assert_eq!(items[0], point_xy);
803 }
804
805 #[test]
806 fn geometry_type_set_serde_multiple() {
807 let mut set = GeometryTypeAndDimensionsSet::new();
808
809 let test_types = vec![
810 GeometryTypeAndDimensions::new(Point, Xy),
811 GeometryTypeAndDimensions::new(LineString, Xyz),
812 GeometryTypeAndDimensions::new(Polygon, Xyzm),
813 ];
814
815 for type_and_dim in &test_types {
816 set.insert(type_and_dim).unwrap();
817 }
818
819 let json = serde_json::to_string(&set).unwrap();
821 assert_eq!(json, "[\"Point\",\"LineString Z\",\"Polygon ZM\"]");
822
823 let deserialized: GeometryTypeAndDimensionsSet = serde_json::from_str(&json).unwrap();
825 assert_eq!(deserialized.size(), test_types.len());
826
827 let items: Vec<_> = deserialized.iter().collect();
828 for type_and_dim in &test_types {
829 assert!(items.contains(type_and_dim));
830 }
831 }
832
833 #[test]
834 fn geometry_type_set_serde_roundtrip() {
835 let mut set = GeometryTypeAndDimensionsSet::new();
836
837 set.insert(&GeometryTypeAndDimensions::new(Point, Xy))
839 .unwrap();
840 set.insert(&GeometryTypeAndDimensions::new(Point, Xyz))
841 .unwrap();
842 set.insert(&GeometryTypeAndDimensions::new(Point, Xym))
843 .unwrap();
844 set.insert(&GeometryTypeAndDimensions::new(Point, Xyzm))
845 .unwrap();
846 set.insert(&GeometryTypeAndDimensions::new(LineString, Xy))
847 .unwrap();
848
849 let json = serde_json::to_string(&set).unwrap();
851 assert_eq!(
852 json,
853 "[\"Point\",\"LineString\",\"Point Z\",\"Point M\",\"Point ZM\"]"
854 );
855
856 let deserialized: GeometryTypeAndDimensionsSet = serde_json::from_str(&json).unwrap();
858
859 assert_eq!(set.size(), deserialized.size());
861
862 let original_items: Vec<_> = set.iter().collect();
863 let deserialized_items: Vec<_> = deserialized.iter().collect();
864
865 assert_eq!(original_items.len(), deserialized_items.len());
866 for item in &original_items {
867 assert!(deserialized_items.contains(item));
868 }
869 }
870}