zerometry/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4mod bounding_box;
5mod coord;
6mod coords;
7mod relation;
8mod segment;
9#[cfg(test)]
10mod test;
11mod zine;
12mod zoint;
13mod zollection;
14mod zolygon;
15mod zulti_lines;
16mod zulti_points;
17mod zulti_polygons;
18
19use std::{io, mem};
20
21pub use bounding_box::BoundingBox;
22pub use coord::Coord;
23pub(crate) use coord::{COORD_SIZE_IN_BYTES, COORD_SIZE_IN_FLOATS};
24pub use coords::Coords;
25use geo::LineString;
26use geo_types::{Geometry, MultiPolygon, Polygon};
27pub use relation::{InputRelation, OutputRelation, RelationBetweenShapes};
28pub use segment::Segment;
29pub use zine::Zine;
30pub use zoint::Zoint;
31pub use zollection::Zollection;
32pub use zolygon::Zolygon;
33pub use zulti_lines::ZultiLines;
34pub use zulti_points::ZultiPoints;
35pub use zulti_polygons::ZultiPolygons;
36
37/// Main structure of this crate, this is the equivalent of a [`geo_types::Geometry`] but serialized.
38#[derive(Debug, Clone, Copy)]
39pub enum Zerometry<'a> {
40    /// Equivalent of a [`geo_types::Point`]
41    Point(Zoint<'a>),
42    /// Equivalent of a [`geo_types::MultiPoint`]
43    MultiPoints(ZultiPoints<'a>),
44    /// Equivalent of a [`geo_types::LineString`]
45    Line(Zine<'a>),
46    /// Equivalent of a [`geo_types::MultiLineString`]
47    MultiLines(ZultiLines<'a>),
48    /// Equivalent of a [`geo_types::Polygon`]
49    Polygon(Zolygon<'a>),
50    /// Equivalent of a [`geo_types::MultiPolygon`]
51    MultiPolygon(ZultiPolygons<'a>),
52    /// Equivalent of a [`geo_types::GeometryCollection`]
53    Collection(Zollection<'a>),
54}
55
56impl<'a> Zerometry<'a> {
57    /// Create a `Zerometry` from a slice of bytes.
58    /// See [`Self::write_from_geometry`] to create the slice of bytes.
59    ///
60    /// # Safety
61    /// The data must be generated from the [`Self::write_from_geometry`] method and be aligned on 64 bits
62    #[inline]
63    pub unsafe fn from_bytes(data: &'a [u8]) -> Result<Self, std::io::Error> {
64        if data.len() < mem::size_of::<u64>() {
65            return Err(io::Error::new(
66                io::ErrorKind::UnexpectedEof,
67                format!(
68                    "Was expecting at least {} bytes but found {}",
69                    mem::size_of::<u64>(),
70                    data.len()
71                ),
72            ));
73        }
74        let tag = u64::from_ne_bytes(
75            data[..mem::size_of::<u64>()]
76                .try_into()
77                .map_err(io::Error::other)?,
78        );
79        let data = &data[mem::size_of::<u64>()..];
80        match tag {
81            0 => Ok(Zerometry::Point(unsafe { Zoint::from_bytes(data) })),
82            1 => Ok(Zerometry::MultiPoints(unsafe {
83                ZultiPoints::from_bytes(data)
84            })),
85            2 => Ok(Zerometry::Polygon(unsafe { Zolygon::from_bytes(data) })),
86            3 => Ok(Zerometry::MultiPolygon(unsafe {
87                ZultiPolygons::from_bytes(data)
88            })),
89            // They're located after because it would be a db-breaking to edit the already existing tags
90            4 => Ok(Zerometry::Line(unsafe { Zine::from_bytes(data) })),
91            5 => Ok(Zerometry::MultiLines(unsafe {
92                ZultiLines::from_bytes(data)
93            })),
94            6 => Ok(Zerometry::Collection(unsafe {
95                Zollection::from_bytes(data)
96            })),
97            _ => Err(std::io::Error::new(
98                std::io::ErrorKind::InvalidData,
99                "Invalid zerometry tag",
100            )),
101        }
102    }
103
104    /// Convert the specified [`geo_types::Geometry`] to a valid [`Zerometry`] slice of bytes in the input buffer.
105    /// This is a destructive operation, the original geometry cannot be recreated as-is from the outputted zerometry:
106    /// - The Line, Triangle and Rectangle gets converted respectively to Zine and Zolygon
107    /// - The collections are flattened to a collection containing one multipoints, one multipolygons and one multilines.
108    pub fn write_from_geometry(
109        writer: &mut Vec<u8>,
110        geometry: &Geometry<f64>,
111    ) -> Result<(), std::io::Error> {
112        // to stay aligned on 64 bits we must add the tag as a u64
113        match geometry {
114            Geometry::Point(point) => {
115                writer.extend_from_slice(&0_u64.to_ne_bytes());
116                Zoint::write_from_geometry(writer, point)?;
117            }
118            Geometry::MultiPoint(multi_point) => {
119                writer.extend_from_slice(&1_u64.to_ne_bytes());
120                ZultiPoints::write_from_geometry(writer, multi_point)?;
121            }
122            Geometry::Polygon(polygon) => {
123                writer.extend_from_slice(&2_u64.to_ne_bytes());
124                Zolygon::write_from_geometry(writer, polygon)?;
125            }
126            Geometry::MultiPolygon(multi_polygon) => {
127                writer.extend_from_slice(&3_u64.to_ne_bytes());
128                ZultiPolygons::write_from_geometry(writer, multi_polygon)?;
129            }
130            Geometry::LineString(line_string) => {
131                writer.extend_from_slice(&4_u64.to_ne_bytes());
132                Zine::write_from_geometry(writer, line_string)?;
133            }
134            Geometry::MultiLineString(multi_line_string) => {
135                writer.extend_from_slice(&5_u64.to_ne_bytes());
136                ZultiLines::write_from_geometry(writer, multi_line_string)?;
137            }
138            Geometry::GeometryCollection(collection) => {
139                writer.extend_from_slice(&6_u64.to_ne_bytes());
140                Zollection::write_from_geometry(writer, collection)?;
141            }
142            // Should never happens since we're working with geogson in meilisearch
143            Geometry::Line(line) => {
144                let line = LineString::new(vec![line.start, line.end]);
145                Self::write_from_geometry(writer, &line.into())?;
146            }
147            Geometry::Rect(rect) => {
148                Self::write_from_geometry(writer, &rect.to_polygon().into())?;
149            }
150            Geometry::Triangle(triangle) => {
151                Self::write_from_geometry(writer, &triangle.to_polygon().into())?;
152            }
153        }
154        Ok(())
155    }
156
157    /// Convert the [`Zerometry`] to a [`Zoint`] if possible. If it was not a point it returns [`None`].
158    #[inline]
159    pub fn to_point(&self) -> Option<Zoint<'_>> {
160        match self {
161            Zerometry::Point(a) => Some(*a),
162            _ => None,
163        }
164    }
165
166    /// Convert the [`Zerometry`] to a [`ZultiPoints`] if possible. If it was not a multi point it returns [`None`].
167    #[inline]
168    pub fn to_multi_points(&self) -> Option<ZultiPoints<'_>> {
169        match self {
170            Zerometry::MultiPoints(a) => Some(*a),
171            _ => None,
172        }
173    }
174
175    /// Convert the [`Zerometry`] to a [`Zine`] if possible. If it was not a line it returns [`None`].
176    #[inline]
177    pub fn to_line(&self) -> Option<Zine<'_>> {
178        match self {
179            Zerometry::Line(a) => Some(*a),
180            _ => None,
181        }
182    }
183
184    /// Convert the [`Zerometry`] to a [`ZultiLines`] if possible. If it was not a multi lines it returns [`None`].
185    #[inline]
186    pub fn to_zulti_lines(&self) -> Option<ZultiLines<'_>> {
187        match self {
188            Zerometry::MultiLines(a) => Some(*a),
189            _ => None,
190        }
191    }
192
193    /// Convert the [`Zerometry`] to a [`Zolygon`] if possible. If it was not a polygon it returns [`None`].
194    #[inline]
195    pub fn to_polygon(&self) -> Option<Zolygon<'_>> {
196        match self {
197            Zerometry::Polygon(a) => Some(*a),
198            _ => None,
199        }
200    }
201
202    /// Convert the [`Zerometry`] to a [`ZultiPolygons`] if possible. If it was not a multi polygons it returns [`None`].
203    #[inline]
204    pub fn to_multi_polygon(&self) -> Option<ZultiPolygons<'_>> {
205        match self {
206            Zerometry::MultiPolygon(a) => Some(*a),
207            _ => None,
208        }
209    }
210
211    /// Convert the [`Zerometry`] to a [`Zollection`] if possible. If it was not a collection it returns [`None`].
212    #[inline]
213    pub fn to_collection(&self) -> Option<Zollection<'_>> {
214        match self {
215            Zerometry::Collection(a) => Some(*a),
216            _ => None,
217        }
218    }
219
220    /// Convert the [`Zerometry`] back to a [`geo_types::Geometry`].
221    /// Don't forget that converting the geometry to a zerometry was a destructive operation.
222    /// This means the geometry you'll get back won't necessarily correspond to your initial geometry.
223    pub fn to_geo(&self) -> geo_types::Geometry<f64> {
224        match self {
225            Zerometry::Point(a) => Geometry::Point(a.to_geo()),
226            Zerometry::MultiPoints(a) => Geometry::MultiPoint(a.to_geo()),
227            Zerometry::Line(a) => Geometry::LineString(a.to_geo()),
228            Zerometry::MultiLines(a) => Geometry::MultiLineString(a.to_geo()),
229            Zerometry::Polygon(a) => Geometry::Polygon(a.to_geo()),
230            Zerometry::MultiPolygon(a) => Geometry::MultiPolygon(a.to_geo()),
231            Zerometry::Collection(zollection) => Geometry::GeometryCollection(zollection.to_geo()),
232        }
233    }
234}
235
236impl<'a> From<Zoint<'a>> for Zerometry<'a> {
237    #[inline]
238    fn from(point: Zoint<'a>) -> Self {
239        Zerometry::Point(point)
240    }
241}
242
243impl<'a> From<ZultiPoints<'a>> for Zerometry<'a> {
244    #[inline]
245    fn from(points: ZultiPoints<'a>) -> Self {
246        Zerometry::MultiPoints(points)
247    }
248}
249
250impl<'a> From<Zolygon<'a>> for Zerometry<'a> {
251    #[inline]
252    fn from(polygon: Zolygon<'a>) -> Self {
253        Zerometry::Polygon(polygon)
254    }
255}
256
257impl<'a> From<ZultiPolygons<'a>> for Zerometry<'a> {
258    #[inline]
259    fn from(polygon: ZultiPolygons<'a>) -> Self {
260        Zerometry::MultiPolygon(polygon)
261    }
262}
263
264impl<'a> RelationBetweenShapes<Zoint<'a>> for Zerometry<'a> {
265    fn relation(&self, other: &Zoint, relation: InputRelation) -> OutputRelation {
266        match self {
267            Zerometry::Point(a) => a.relation(other, relation),
268            Zerometry::MultiPoints(a) => a.relation(other, relation),
269            Zerometry::Line(a) => a.relation(other, relation),
270            Zerometry::MultiLines(a) => a.relation(other, relation),
271            Zerometry::Polygon(a) => a.relation(other, relation),
272            Zerometry::MultiPolygon(a) => a.relation(other, relation),
273            Zerometry::Collection(a) => a.relation(other, relation),
274        }
275    }
276}
277
278impl<'a> RelationBetweenShapes<ZultiPoints<'a>> for Zerometry<'a> {
279    fn relation(&self, other: &ZultiPoints, relation: InputRelation) -> OutputRelation {
280        match self {
281            Zerometry::Point(a) => a.relation(other, relation),
282            Zerometry::MultiPoints(a) => a.relation(other, relation),
283            Zerometry::Line(a) => a.relation(other, relation),
284            Zerometry::MultiLines(a) => a.relation(other, relation),
285            Zerometry::Polygon(a) => a.relation(other, relation),
286            Zerometry::MultiPolygon(a) => a.relation(other, relation),
287            Zerometry::Collection(a) => a.relation(other, relation),
288        }
289    }
290}
291
292impl<'a> RelationBetweenShapes<Zine<'a>> for Zerometry<'a> {
293    fn relation(&self, other: &Zine, relation: InputRelation) -> OutputRelation {
294        match self {
295            Zerometry::Point(a) => a.relation(other, relation),
296            Zerometry::MultiPoints(a) => a.relation(other, relation),
297            Zerometry::MultiLines(a) => a.relation(other, relation),
298            Zerometry::Line(a) => a.relation(other, relation),
299            Zerometry::Polygon(a) => a.relation(other, relation),
300            Zerometry::MultiPolygon(a) => a.relation(other, relation),
301            Zerometry::Collection(a) => a.relation(other, relation),
302        }
303    }
304}
305
306impl<'a> RelationBetweenShapes<ZultiLines<'a>> for Zerometry<'a> {
307    fn relation(&self, other: &ZultiLines, relation: InputRelation) -> OutputRelation {
308        match self {
309            Zerometry::Point(a) => a.relation(other, relation),
310            Zerometry::MultiPoints(a) => a.relation(other, relation),
311            Zerometry::MultiLines(a) => a.relation(other, relation),
312            Zerometry::Line(a) => a.relation(other, relation),
313            Zerometry::Polygon(a) => a.relation(other, relation),
314            Zerometry::MultiPolygon(a) => a.relation(other, relation),
315            Zerometry::Collection(a) => a.relation(other, relation),
316        }
317    }
318}
319
320impl<'a> RelationBetweenShapes<Zolygon<'a>> for Zerometry<'a> {
321    fn relation(&self, other: &Zolygon, relation: InputRelation) -> OutputRelation {
322        match self {
323            Zerometry::Point(a) => a.relation(other, relation),
324            Zerometry::MultiPoints(a) => a.relation(other, relation),
325            Zerometry::MultiLines(a) => a.relation(other, relation),
326            Zerometry::Line(a) => a.relation(other, relation),
327            Zerometry::Polygon(a) => a.relation(other, relation),
328            Zerometry::MultiPolygon(a) => a.relation(other, relation),
329            Zerometry::Collection(a) => a.relation(other, relation),
330        }
331    }
332}
333
334impl<'a> RelationBetweenShapes<ZultiPolygons<'a>> for Zerometry<'a> {
335    fn relation(&self, other: &ZultiPolygons, relation: InputRelation) -> OutputRelation {
336        match self {
337            Zerometry::Point(a) => a.relation(other, relation),
338            Zerometry::MultiPoints(a) => a.relation(other, relation),
339            Zerometry::MultiLines(a) => a.relation(other, relation),
340            Zerometry::Line(a) => a.relation(other, relation),
341            Zerometry::Polygon(a) => a.relation(other, relation),
342            Zerometry::MultiPolygon(a) => a.relation(other, relation),
343            Zerometry::Collection(a) => a.relation(other, relation),
344        }
345    }
346}
347
348impl<'a> RelationBetweenShapes<Zollection<'a>> for Zerometry<'a> {
349    fn relation(&self, other: &Zollection, relation: InputRelation) -> OutputRelation {
350        match self {
351            Zerometry::Point(a) => a.relation(other, relation),
352            Zerometry::MultiPoints(a) => a.relation(other, relation),
353            Zerometry::MultiLines(a) => a.relation(other, relation),
354            Zerometry::Line(a) => a.relation(other, relation),
355            Zerometry::Polygon(a) => a.relation(other, relation),
356            Zerometry::MultiPolygon(a) => a.relation(other, relation),
357            Zerometry::Collection(a) => a.relation(other, relation),
358        }
359    }
360}
361
362impl<'a> RelationBetweenShapes<Zerometry<'a>> for Zerometry<'a> {
363    fn relation(&self, other: &Zerometry, relation: InputRelation) -> OutputRelation {
364        match other {
365            Zerometry::Point(a) => self.relation(a, relation),
366            Zerometry::MultiPoints(a) => self.relation(a, relation),
367            Zerometry::Line(a) => a.relation(other, relation),
368            Zerometry::MultiLines(a) => self.relation(a, relation),
369            Zerometry::Polygon(a) => self.relation(a, relation),
370            Zerometry::MultiPolygon(a) => self.relation(a, relation),
371            Zerometry::Collection(a) => self.relation(a, relation),
372        }
373    }
374}
375
376impl<'a> RelationBetweenShapes<Geometry<f64>> for Zerometry<'a> {
377    fn relation(&self, other: &Geometry<f64>, relation: InputRelation) -> OutputRelation {
378        let mut buffer = Vec::new();
379        Zerometry::write_from_geometry(&mut buffer, other).unwrap();
380        let other = unsafe { Zerometry::from_bytes(&buffer).unwrap() };
381        self.relation(&other, relation)
382    }
383}
384
385impl<'a> RelationBetweenShapes<Zerometry<'a>> for Geometry<f64> {
386    fn relation(&self, other: &Zerometry<'a>, relation: InputRelation) -> OutputRelation {
387        let mut buffer = Vec::new();
388        Zerometry::write_from_geometry(&mut buffer, self).unwrap();
389        let this = unsafe { Zerometry::from_bytes(&buffer).unwrap() };
390        this.relation(other, relation)
391    }
392}
393
394impl<'a> RelationBetweenShapes<Polygon<f64>> for Zerometry<'a> {
395    fn relation(&self, other: &Polygon<f64>, relation: InputRelation) -> OutputRelation {
396        let mut buffer = Vec::new();
397        Zerometry::write_from_geometry(&mut buffer, &Geometry::Polygon(other.clone())).unwrap();
398        let other = unsafe { Zerometry::from_bytes(&buffer).unwrap() };
399        self.relation(&other, relation)
400    }
401}
402
403impl<'a> RelationBetweenShapes<MultiPolygon<f64>> for Zerometry<'a> {
404    fn relation(&self, other: &MultiPolygon<f64>, relation: InputRelation) -> OutputRelation {
405        let mut buffer = Vec::new();
406        Zerometry::write_from_geometry(&mut buffer, &Geometry::MultiPolygon(other.clone()))
407            .unwrap();
408        let other = unsafe { Zerometry::from_bytes(&buffer).unwrap() };
409        self.relation(&other, relation)
410    }
411}
412
413impl PartialEq<Geometry> for Zerometry<'_> {
414    fn eq(&self, other: &Geometry) -> bool {
415        match (self, other) {
416            (Zerometry::Point(zoint), Geometry::Point(point)) => zoint.eq(point),
417            (Zerometry::MultiPoints(zulti_points), Geometry::MultiPoint(multi_point)) => {
418                zulti_points.eq(multi_point)
419            }
420            (Zerometry::Line(zine), Geometry::LineString(line_string)) => zine.eq(line_string),
421            (Zerometry::MultiLines(zulti_lines), Geometry::MultiLineString(multi_line_string)) => {
422                zulti_lines.eq(multi_line_string)
423            }
424            (Zerometry::Polygon(zolygon), Geometry::Polygon(polygon)) => zolygon.eq(polygon),
425            (Zerometry::MultiPolygon(zulti_polygon), Geometry::MultiPolygon(multi_polygon)) => {
426                zulti_polygon.eq(multi_polygon)
427            }
428            _ => false,
429        }
430    }
431}
432
433#[cfg(test)]
434mod zerometry_test {
435    use geo_types::geometry;
436
437    use crate::Zerometry;
438
439    #[test]
440    fn naive_point_roundtrip() {
441        let point = geometry::Geometry::Point(geometry::Point::new(45.0, 65.0));
442        let mut buf = Vec::new();
443        Zerometry::write_from_geometry(&mut buf, &point).unwrap();
444        let zoint = unsafe { Zerometry::from_bytes(&buf).unwrap() };
445        assert_eq!(zoint, point);
446    }
447
448    #[test]
449    fn naive_multi_point_roundtrip() {
450        let multi_point = geometry::Geometry::MultiPoint(geometry::MultiPoint::new(vec![]));
451        let mut buf = Vec::new();
452        Zerometry::write_from_geometry(&mut buf, &multi_point).unwrap();
453        let zulti_point = unsafe { Zerometry::from_bytes(&buf).unwrap() };
454        assert_eq!(zulti_point, multi_point);
455
456        let multi_point = geometry::Geometry::MultiPoint(geometry::MultiPoint::new(vec![
457            geometry::Point::new(45.0, 65.0),
458            geometry::Point::new(46.0, 66.0),
459            geometry::Point::new(44.0, 64.0),
460            geometry::Point::new(45.0, 65.0),
461        ]));
462        let mut buf = Vec::new();
463        Zerometry::write_from_geometry(&mut buf, &multi_point).unwrap();
464        let zulti_point = unsafe { Zerometry::from_bytes(&buf).unwrap() };
465        assert_eq!(zulti_point, multi_point);
466    }
467
468    #[test]
469    fn naive_line_string_roundtrip() {
470        let line_string = geometry::Geometry::LineString(geometry::LineString::new(vec![]));
471        let mut buf = Vec::new();
472        Zerometry::write_from_geometry(&mut buf, &line_string).unwrap();
473        let zine_string = unsafe { Zerometry::from_bytes(&buf).unwrap() };
474        assert_eq!(zine_string, line_string);
475
476        let line_string = geometry::Geometry::LineString(geometry::LineString::new(vec![
477            geometry::Coord { x: 45.0, y: 25.0 },
478            geometry::Coord { x: 46.0, y: 24.0 },
479            geometry::Coord { x: 45.0, y: 25.0 },
480        ]));
481        let mut buf = Vec::new();
482        Zerometry::write_from_geometry(&mut buf, &line_string).unwrap();
483        let zine_string = unsafe { Zerometry::from_bytes(&buf).unwrap() };
484        assert_eq!(zine_string, line_string);
485    }
486
487    #[test]
488    fn naive_multi_line_string_roundtrip() {
489        let multi_line_string =
490            geometry::Geometry::MultiLineString(geometry::MultiLineString::new(vec![]));
491        let mut buf = Vec::new();
492        Zerometry::write_from_geometry(&mut buf, &multi_line_string).unwrap();
493        let zulti_line_string = unsafe { Zerometry::from_bytes(&buf).unwrap() };
494        assert_eq!(zulti_line_string, multi_line_string);
495
496        let multi_line_string =
497            geometry::Geometry::MultiLineString(geometry::MultiLineString::new(vec![
498                geometry::LineString::new(vec![
499                    geometry::Coord { x: 45.0, y: 25.0 },
500                    geometry::Coord { x: 46.0, y: 24.0 },
501                    geometry::Coord { x: 45.0, y: 25.0 },
502                ]),
503                geometry::LineString::new(vec![]),
504                geometry::LineString::new(vec![
505                    geometry::Coord { x: 66.0, y: 46.0 },
506                    geometry::Coord { x: 47.0, y: 34.0 },
507                    geometry::Coord { x: 66.0, y: 26.0 },
508                ]),
509            ]));
510        let mut buf = Vec::new();
511        Zerometry::write_from_geometry(&mut buf, &multi_line_string).unwrap();
512        let zulti_line_string = unsafe { Zerometry::from_bytes(&buf).unwrap() };
513        assert_eq!(zulti_line_string, multi_line_string);
514
515        let multi_line_string =
516            geometry::Geometry::MultiLineString(geometry::MultiLineString::new(vec![
517                geometry::LineString::new(vec![
518                    geometry::Coord { x: 45.0, y: 25.0 },
519                    geometry::Coord { x: 46.0, y: 24.0 },
520                    geometry::Coord { x: 45.0, y: 25.0 },
521                ]),
522                geometry::LineString::new(vec![
523                    geometry::Coord { x: 55.0, y: 25.0 },
524                    geometry::Coord { x: 46.0, y: 34.0 },
525                    geometry::Coord { x: 55.0, y: 25.0 },
526                ]),
527                geometry::LineString::new(vec![
528                    geometry::Coord { x: 66.0, y: 46.0 },
529                    geometry::Coord { x: 47.0, y: 34.0 },
530                    geometry::Coord { x: 66.0, y: 26.0 },
531                ]),
532            ]));
533        let mut buf = Vec::new();
534        Zerometry::write_from_geometry(&mut buf, &multi_line_string).unwrap();
535        let zulti_line_string = unsafe { Zerometry::from_bytes(&buf).unwrap() };
536        assert_eq!(zulti_line_string, multi_line_string);
537    }
538
539    #[test]
540    fn naive_polygon_roundtrip() {
541        let polygon = geometry::Geometry::Polygon(geometry::Polygon::new(
542            geometry::LineString::new(vec![]),
543            vec![],
544        ));
545        let mut buf = Vec::new();
546        Zerometry::write_from_geometry(&mut buf, &polygon).unwrap();
547        let zolygon = unsafe { Zerometry::from_bytes(&buf).unwrap() };
548        assert_eq!(zolygon, polygon);
549
550        let polygon = geometry::Geometry::Polygon(geometry::Polygon::new(
551            geometry::LineString::new(vec![
552                geometry::Coord { x: 66.0, y: 46.0 },
553                geometry::Coord { x: 47.0, y: 34.0 },
554                geometry::Coord { x: 66.0, y: 26.0 },
555            ]),
556            vec![],
557        ));
558        let mut buf = Vec::new();
559        Zerometry::write_from_geometry(&mut buf, &polygon).unwrap();
560        let zolygon = unsafe { Zerometry::from_bytes(&buf).unwrap() };
561        assert_eq!(zolygon, polygon);
562    }
563
564    #[test]
565    fn naive_multi_polygon_roundtrip() {
566        let multi_polygon = geometry::Geometry::MultiPolygon(geometry::MultiPolygon::new(vec![]));
567        let mut buf = Vec::new();
568        Zerometry::write_from_geometry(&mut buf, &multi_polygon).unwrap();
569        let zulti_polygon = unsafe { Zerometry::from_bytes(&buf).unwrap() };
570        assert_eq!(zulti_polygon, multi_polygon);
571
572        let multi_polygon = geometry::Geometry::MultiPolygon(geometry::MultiPolygon::new(vec![
573            geometry::Polygon::new(
574                geometry::LineString::new(vec![
575                    geometry::Coord { x: 66.0, y: 46.0 },
576                    geometry::Coord { x: 47.0, y: 34.0 },
577                    geometry::Coord { x: 66.0, y: 26.0 },
578                ]),
579                vec![],
580            ),
581            geometry::Polygon::new(
582                geometry::LineString::new(vec![
583                    geometry::Coord { x: 86.0, y: 48.0 },
584                    geometry::Coord { x: 67.0, y: 36.0 },
585                    geometry::Coord { x: 86.0, y: 28.0 },
586                ]),
587                vec![],
588            ),
589        ]));
590        let mut buf = Vec::new();
591        Zerometry::write_from_geometry(&mut buf, &multi_polygon).unwrap();
592        let zulti_polygon = unsafe { Zerometry::from_bytes(&buf).unwrap() };
593        assert_eq!(zulti_polygon, multi_polygon);
594    }
595
596    #[test]
597    fn naive_geometry_collection_roundtrip() {
598        /*
599        let geometry_collection =
600            geometry::Geometry::GeometryCollection(geometry::GeometryCollection::new_from(todo!()));
601        let mut buf = Vec::new();
602        Zerometry::write_from_geometry(&mut buf, &geometry_collection).unwrap();
603        let zeometry_collection = Zerometry::from_bytes(&buf).unwrap();
604        assert_eq!(zeometry_collection, geometry_collection);
605        */
606    }
607}