postgis_butmaintained/ewkb/
geometry.rs

1use crate::ewkb::*;
2
3macro_rules! geometry_container_type {
4    // geometries containing lines and polygons
5    ($geotypetrait:ident for $geotype:ident contains $itemtype:ident named $itemname:ident) => {
6        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7        #[derive(PartialEq, Clone, Debug)]
8        pub struct $geotype<P: postgis::Point + EwkbRead> {
9            pub $itemname: Vec<$itemtype<P>>,
10            pub srid: Option<i32>,
11        }
12
13        impl<P> Default for $geotype<P>
14        where
15                    P: postgis::Point + EwkbRead,
16         {
17            fn default() -> Self {
18                Self::new()
19            }
20        }
21
22        impl<P> $geotype<P>
23        where
24            P: postgis::Point + EwkbRead,
25        {
26            pub fn new() -> $geotype<P> {
27                $geotype {
28                    $itemname: Vec::new(),
29                    srid: None,
30                }
31            }
32        }
33
34        impl<P> FromIterator<$itemtype<P>> for $geotype<P>
35        where
36            P: postgis::Point + EwkbRead,
37        {
38            #[inline]
39            fn from_iter<I: IntoIterator<Item = $itemtype<P>>>(iterable: I) -> $geotype<P> {
40                let iterator = iterable.into_iter();
41                let (lower, _) = iterator.size_hint();
42                let mut ret = $geotype::new();
43                ret.$itemname.reserve(lower);
44                for item in iterator {
45                    ret.$itemname.push(item);
46                }
47                ret
48            }
49        }
50
51        impl<'a, P> postgis::$geotypetrait<'a> for $geotype<P>
52        where
53            P: 'a + postgis::Point + EwkbRead,
54        {
55            type ItemType = $itemtype<P>;
56            type Iter = Iter<'a, Self::ItemType>;
57            fn $itemname(&'a self) -> Self::Iter {
58                self.$itemname.iter()
59            }
60        }
61    };
62}
63
64macro_rules! impl_read_for_geometry_container_type {
65    (singletype $geotype:ident contains $itemtype:ident named $itemname:ident) => {
66        impl<P> EwkbRead for $geotype<P>
67        where
68            P: postgis::Point + EwkbRead,
69        {
70            fn point_type() -> PointType {
71                P::point_type()
72            }
73            fn read_ewkb_body<R: Read>(
74                raw: &mut R,
75                is_be: bool,
76                type_id: u32,
77                srid: Option<i32>,
78            ) -> Result<Self, Error> {
79                let mut $itemname: Vec<$itemtype<P>> = vec![];
80                let size = read_u32(raw, is_be)? as usize;
81                for _ in 0..size {
82                    $itemname.push($itemtype::read_ewkb_body(raw, is_be, type_id, srid)?);
83                }
84                Ok($geotype::<P> {
85                    $itemname: $itemname,
86                    srid,
87                })
88            }
89        }
90    };
91    (multitype $geotype:ident contains $itemtype:ident named $itemname:ident) => {
92        impl<P> EwkbRead for $geotype<P>
93        where
94            P: postgis::Point + EwkbRead,
95        {
96            fn point_type() -> PointType {
97                P::point_type()
98            }
99            fn read_ewkb_body<R: Read>(
100                raw: &mut R,
101                is_be: bool,
102                _type_id: u32,
103                srid: Option<i32>,
104            ) -> Result<Self, Error> {
105                let mut $itemname: Vec<$itemtype<P>> = vec![];
106                let size = read_u32(raw, is_be)? as usize;
107                for _ in 0..size {
108                    $itemname.push($itemtype::read_ewkb(raw)?);
109                }
110                Ok($geotype::<P> {
111                    $itemname: $itemname,
112                    srid,
113                })
114            }
115        }
116    };
117}
118
119macro_rules! geometry_container_write {
120    ($geotypetrait:ident and $asewkbtype:ident for $geotype:ident to $ewkbtype:ident with type code $typecode:expr, contains $ewkbitemtype:ident, $itemtype:ident as $itemtypetrait:ident named $itemname:ident, command $writecmd:ident) => {
121        pub struct $ewkbtype<'a, P, I, T, J>
122        where
123            P: 'a + postgis::Point,
124            I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
125            T: 'a + postgis::$itemtypetrait<'a, ItemType = P, Iter = I>,
126            J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
127        {
128            pub geom: &'a dyn postgis::$geotypetrait<'a, ItemType = T, Iter = J>,
129            pub srid: Option<i32>,
130            pub point_type: PointType,
131        }
132
133        pub trait $asewkbtype<'a> {
134            type PointType: 'a + postgis::Point;
135            type PointIter: Iterator<Item = &'a Self::PointType>
136                + ExactSizeIterator<Item = &'a Self::PointType>;
137            type ItemType: 'a
138                + postgis::$itemtypetrait<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
139            type Iter: Iterator<Item = &'a Self::ItemType>
140                + ExactSizeIterator<Item = &'a Self::ItemType>;
141            fn as_ewkb(
142                &'a self,
143            ) -> $ewkbtype<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter>;
144        }
145
146        impl<'a, P, I, T, J> fmt::Debug for $ewkbtype<'a, P, I, T, J>
147        where
148            P: 'a + postgis::Point,
149            I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
150            T: 'a + postgis::$itemtypetrait<'a, ItemType = P, Iter = I>,
151            J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
152        {
153            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154                write!(f, stringify!($ewkbtype))?; //TODO
155                Ok(())
156            }
157        }
158
159        impl<'a, P, I, T, J> EwkbWrite for $ewkbtype<'a, P, I, T, J>
160        where
161            P: 'a + postgis::Point,
162            I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
163            T: 'a + postgis::$itemtypetrait<'a, ItemType = P, Iter = I>,
164            J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
165        {
166            fn opt_srid(&self) -> Option<i32> {
167                self.srid
168            }
169
170            fn type_id(&self) -> u32 {
171                $typecode | Self::wkb_type_id(&self.point_type, self.srid)
172            }
173
174            fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
175                w.write_u32::<LittleEndian>(self.geom.$itemname().len() as u32)?;
176                for geom in self.geom.$itemname() {
177                    let wkb = $ewkbitemtype {
178                        geom,
179                        srid: None,
180                        point_type: self.point_type.clone(),
181                    };
182                    wkb.$writecmd(w)?;
183                }
184                Ok(())
185            }
186        }
187
188        impl<'a, P> $asewkbtype<'a> for $geotype<P>
189        where
190            P: 'a + postgis::Point + EwkbRead,
191        {
192            type PointType = P;
193            type PointIter = Iter<'a, P>;
194            type ItemType = $itemtype<P>;
195            type Iter = Iter<'a, Self::ItemType>;
196            fn as_ewkb(
197                &'a self,
198            ) -> $ewkbtype<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter> {
199                $ewkbtype {
200                    geom: self,
201                    srid: self.srid,
202                    point_type: Self::PointType::point_type(),
203                }
204            }
205        }
206    };
207    (multipoly $geotypetrait:ident and $asewkbtype:ident for $geotype:ident to $ewkbtype:ident with type code $typecode:expr, contains $ewkbitemtype:ident, $itemtype:ident as $itemtypetrait:ident named $itemname:ident, command $writecmd:ident) => {
208        pub struct $ewkbtype<'a, P, I, L, K, T, J>
209        where
210            P: 'a + postgis::Point,
211            I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
212            L: 'a + postgis::LineString<'a, ItemType = P, Iter = I>,
213            K: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
214            T: 'a + postgis::$itemtypetrait<'a, ItemType = L, Iter = K>,
215            J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
216        {
217            pub geom: &'a dyn postgis::$geotypetrait<'a, ItemType = T, Iter = J>,
218            pub srid: Option<i32>,
219            pub point_type: PointType,
220        }
221
222        pub trait $asewkbtype<'a> {
223            type PointType: 'a + postgis::Point;
224            type PointIter: Iterator<Item = &'a Self::PointType>
225                + ExactSizeIterator<Item = &'a Self::PointType>;
226            type LineType: 'a
227                + postgis::LineString<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
228            type LineIter: Iterator<Item = &'a Self::LineType>
229                + ExactSizeIterator<Item = &'a Self::LineType>;
230            type ItemType: 'a
231                + postgis::$itemtypetrait<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
232            type Iter: Iterator<Item = &'a Self::ItemType>
233                + ExactSizeIterator<Item = &'a Self::ItemType>;
234            fn as_ewkb(
235                &'a self,
236            ) -> $ewkbtype<
237                'a,
238                Self::PointType,
239                Self::PointIter,
240                Self::LineType,
241                Self::LineIter,
242                Self::ItemType,
243                Self::Iter,
244            >;
245        }
246
247        impl<'a, P, I, L, K, T, J> fmt::Debug for $ewkbtype<'a, P, I, L, K, T, J>
248        where
249            P: 'a + postgis::Point,
250            I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
251            L: 'a + postgis::LineString<'a, ItemType = P, Iter = I>,
252            K: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
253            T: 'a + postgis::$itemtypetrait<'a, ItemType = L, Iter = K>,
254            J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
255        {
256            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
257                write!(f, stringify!($ewkbtype))?; //TODO
258                Ok(())
259            }
260        }
261
262        impl<'a, P, I, L, K, T, J> EwkbWrite for $ewkbtype<'a, P, I, L, K, T, J>
263        where
264            P: 'a + postgis::Point,
265            I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
266            L: 'a + postgis::LineString<'a, ItemType = P, Iter = I>,
267            K: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
268            T: 'a + postgis::$itemtypetrait<'a, ItemType = L, Iter = K>,
269            J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
270        {
271            fn opt_srid(&self) -> Option<i32> {
272                self.srid
273            }
274
275            fn type_id(&self) -> u32 {
276                $typecode | Self::wkb_type_id(&self.point_type, self.srid)
277            }
278
279            fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
280                w.write_u32::<LittleEndian>(self.geom.$itemname().len() as u32)?;
281                for geom in self.geom.$itemname() {
282                    let wkb = $ewkbitemtype {
283                        geom,
284                        srid: None,
285                        point_type: self.point_type.clone(),
286                    };
287                    wkb.$writecmd(w)?;
288                }
289                Ok(())
290            }
291        }
292
293        impl<'a, P> $asewkbtype<'a> for $geotype<P>
294        where
295            P: 'a + postgis::Point + EwkbRead,
296        {
297            type PointType = P;
298            type PointIter = Iter<'a, P>;
299            type LineType = LineStringT<P>;
300            type LineIter = Iter<'a, Self::LineType>;
301            type ItemType = $itemtype<P>;
302            type Iter = Iter<'a, Self::ItemType>;
303            fn as_ewkb(
304                &'a self,
305            ) -> $ewkbtype<
306                'a,
307                Self::PointType,
308                Self::PointIter,
309                Self::LineType,
310                Self::LineIter,
311                Self::ItemType,
312                Self::Iter,
313            > {
314                $ewkbtype {
315                    geom: self,
316                    srid: self.srid,
317                    point_type: Self::PointType::point_type(),
318                }
319            }
320        }
321    };
322}
323
324geometry_container_type!(Polygon for PolygonT contains LineStringT named rings);
325impl_read_for_geometry_container_type!(singletype PolygonT contains LineStringT named rings);
326geometry_container_write!(Polygon and AsEwkbPolygon for PolygonT
327                          to EwkbPolygon with type code 0x03,
328                          contains EwkbLineString,LineStringT as LineString named rings,
329                          command write_ewkb_body);
330
331/// OGC Polygon type
332pub type Polygon = PolygonT<Point>;
333/// OGC PolygonZ type
334pub type PolygonZ = PolygonT<PointZ>;
335/// OGC PolygonM type
336pub type PolygonM = PolygonT<PointM>;
337/// OGC PolygonZM type
338pub type PolygonZM = PolygonT<PointZM>;
339
340geometry_container_type!(MultiLineString for MultiLineStringT contains LineStringT named lines);
341impl_read_for_geometry_container_type!(multitype MultiLineStringT contains LineStringT named lines);
342geometry_container_write!(MultiLineString and AsEwkbMultiLineString for MultiLineStringT
343                          to EwkbMultiLineString with type code 0x05,
344                          contains EwkbLineString,LineStringT as LineString named lines,
345                          command write_ewkb);
346
347/// OGC MultiLineString type
348pub type MultiLineString = MultiLineStringT<Point>;
349/// OGC MultiLineStringZ type
350pub type MultiLineStringZ = MultiLineStringT<PointZ>;
351/// OGC MultiLineStringM type
352pub type MultiLineStringM = MultiLineStringT<PointM>;
353/// OGC MultiLineStringZM type
354pub type MultiLineStringZM = MultiLineStringT<PointZM>;
355
356geometry_container_type!(MultiPolygon for MultiPolygonT contains PolygonT named polygons);
357impl_read_for_geometry_container_type!(multitype MultiPolygonT contains PolygonT named polygons);
358geometry_container_write!(multipoly MultiPolygon and AsEwkbMultiPolygon for MultiPolygonT
359                          to EwkbMultiPolygon with type code 0x06,
360                          contains EwkbPolygon,PolygonT as Polygon named polygons,
361                          command write_ewkb);
362
363/// OGC MultiPolygon type
364pub type MultiPolygon = MultiPolygonT<Point>;
365/// OGC MultiPolygonZ type
366pub type MultiPolygonZ = MultiPolygonT<PointZ>;
367/// OGC MultiPolygonM type
368pub type MultiPolygonM = MultiPolygonT<PointM>;
369/// OGC MultiPolygonZM type
370pub type MultiPolygonZM = MultiPolygonT<PointZM>;
371
372/// Generic Geometry Data Type
373#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
374#[derive(Clone, Debug)]
375pub enum GeometryT<P: postgis::Point + EwkbRead> {
376    Point(P),
377    LineString(LineStringT<P>),
378    Polygon(PolygonT<P>),
379    MultiPoint(MultiPointT<P>),
380    MultiLineString(MultiLineStringT<P>),
381    MultiPolygon(MultiPolygonT<P>),
382    GeometryCollection(GeometryCollectionT<P>),
383}
384
385impl<'a, P> postgis::Geometry<'a> for GeometryT<P>
386where
387    P: 'a + postgis::Point + EwkbRead,
388{
389    type Point = P;
390    type LineString = LineStringT<P>;
391    type Polygon = PolygonT<P>;
392    type MultiPoint = MultiPointT<P>;
393    type MultiLineString = MultiLineStringT<P>;
394    type MultiPolygon = MultiPolygonT<P>;
395    type GeometryCollection = GeometryCollectionT<P>;
396    fn as_type(
397        &'a self,
398    ) -> postgis::GeometryType<
399        'a,
400        P,
401        LineStringT<P>,
402        PolygonT<P>,
403        MultiPointT<P>,
404        MultiLineStringT<P>,
405        MultiPolygonT<P>,
406        GeometryCollectionT<P>,
407    > {
408        use crate::ewkb::GeometryT as A;
409        use crate::types::GeometryType as B;
410        match *self {
411            A::Point(ref geom) => B::Point(geom),
412            A::LineString(ref geom) => B::LineString(geom),
413            A::Polygon(ref geom) => B::Polygon(geom),
414            A::MultiPoint(ref geom) => B::MultiPoint(geom),
415            A::MultiLineString(ref geom) => B::MultiLineString(geom),
416            A::MultiPolygon(ref geom) => B::MultiPolygon(geom),
417            A::GeometryCollection(ref geom) => B::GeometryCollection(geom),
418        }
419    }
420}
421
422impl<P> EwkbRead for GeometryT<P>
423where
424    P: postgis::Point + EwkbRead,
425{
426    fn point_type() -> PointType {
427        P::point_type()
428    }
429    fn read_ewkb<R: Read>(raw: &mut R) -> Result<Self, Error> {
430        let byte_order = raw.read_i8()?;
431        let is_be = byte_order == 0i8;
432
433        let type_id = read_u32(raw, is_be)?;
434        let mut srid: Option<i32> = None;
435        if type_id & 0x20000000 == 0x20000000 {
436            srid = Some(read_i32(raw, is_be)?);
437        }
438
439        let geom = match type_id & 0xff {
440            0x01 => GeometryT::Point(P::read_ewkb_body(raw, is_be, type_id, srid)?),
441            0x02 => {
442                GeometryT::LineString(LineStringT::<P>::read_ewkb_body(raw, is_be, type_id, srid)?)
443            }
444            0x03 => GeometryT::Polygon(PolygonT::read_ewkb_body(raw, is_be, type_id, srid)?),
445            0x04 => GeometryT::MultiPoint(MultiPointT::read_ewkb_body(raw, is_be, type_id, srid)?),
446            0x05 => GeometryT::MultiLineString(MultiLineStringT::read_ewkb_body(
447                raw, is_be, type_id, srid,
448            )?),
449            0x06 => {
450                GeometryT::MultiPolygon(MultiPolygonT::read_ewkb_body(raw, is_be, type_id, srid)?)
451            }
452            0x07 => GeometryT::GeometryCollection(GeometryCollectionT::read_ewkb_body(
453                raw, is_be, type_id, srid,
454            )?),
455            _ => {
456                return Err(Error::Read(format!(
457                    "Error reading generic geometry type - unsupported type id {}.",
458                    type_id
459                )))
460            }
461        };
462        Ok(geom)
463    }
464    fn read_ewkb_body<R: Read>(
465        _raw: &mut R,
466        _is_be: bool,
467        _type_id: u32,
468        _srid: Option<i32>,
469    ) -> Result<Self, Error> {
470        panic!("Not used for generic geometry type")
471    }
472}
473
474pub enum EwkbGeometry<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
475where
476    P: 'a + postgis::Point,
477    PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
478    MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
479    L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
480    LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
481    ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
482    Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
483    YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
484    MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
485    G: 'a
486        + postgis::Geometry<
487            'a,
488            Point = P,
489            LineString = L,
490            Polygon = Y,
491            MultiPoint = MP,
492            MultiLineString = ML,
493            MultiPolygon = MY,
494            GeometryCollection = GC,
495        >,
496    GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
497    GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
498{
499    Point(EwkbPoint<'a>),
500    LineString(EwkbLineString<'a, P, PI>),
501    Polygon(EwkbPolygon<'a, P, PI, L, LI>),
502    MultiPoint(EwkbMultiPoint<'a, P, PI>),
503    MultiLineString(EwkbMultiLineString<'a, P, PI, L, LI>),
504    MultiPolygon(EwkbMultiPolygon<'a, P, PI, L, LI, Y, YI>),
505    GeometryCollection(EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>),
506}
507
508pub trait AsEwkbGeometry<'a> {
509    type PointType: 'a + postgis::Point + EwkbRead;
510    type PointIter: Iterator<Item = &'a Self::PointType>
511        + ExactSizeIterator<Item = &'a Self::PointType>;
512    type MultiPointType: 'a
513        + postgis::MultiPoint<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
514    type LineType: 'a + postgis::LineString<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
515    type LineIter: Iterator<Item = &'a Self::LineType>
516        + ExactSizeIterator<Item = &'a Self::LineType>;
517    type MultiLineType: 'a
518        + postgis::MultiLineString<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
519    type PolyType: 'a + postgis::Polygon<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
520    type PolyIter: Iterator<Item = &'a Self::PolyType>
521        + ExactSizeIterator<Item = &'a Self::PolyType>;
522    type MultiPolyType: 'a
523        + postgis::MultiPolygon<'a, ItemType = Self::PolyType, Iter = Self::PolyIter>;
524    type GeomType: 'a
525        + postgis::Geometry<
526            'a,
527            Point = Self::PointType,
528            LineString = Self::LineType,
529            Polygon = Self::PolyType,
530            MultiPoint = Self::MultiPointType,
531            MultiLineString = Self::MultiLineType,
532            MultiPolygon = Self::MultiPolyType,
533            GeometryCollection = Self::GeomCollection,
534        >;
535    type GeomIter: Iterator<Item = &'a Self::GeomType>
536        + ExactSizeIterator<Item = &'a Self::GeomType>;
537    type GeomCollection: 'a
538        + postgis::GeometryCollection<'a, ItemType = Self::GeomType, Iter = Self::GeomIter>;
539    fn as_ewkb(
540        &'a self,
541    ) -> EwkbGeometry<
542        'a,
543        Self::PointType,
544        Self::PointIter,
545        Self::MultiPointType,
546        Self::LineType,
547        Self::LineIter,
548        Self::MultiLineType,
549        Self::PolyType,
550        Self::PolyIter,
551        Self::MultiPolyType,
552        Self::GeomType,
553        Self::GeomIter,
554        Self::GeomCollection,
555    >;
556}
557
558impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> fmt::Debug
559    for EwkbGeometry<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
560where
561    P: 'a + postgis::Point,
562    PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
563    MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
564    L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
565    LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
566    ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
567    Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
568    YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
569    MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
570    G: 'a
571        + postgis::Geometry<
572            'a,
573            Point = P,
574            LineString = L,
575            Polygon = Y,
576            MultiPoint = MP,
577            MultiLineString = ML,
578            MultiPolygon = MY,
579            GeometryCollection = GC,
580        >,
581    GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
582    GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
583{
584    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
585        write!(f, stringify!(EwkbGeometry))?; //TODO
586        Ok(())
587    }
588}
589
590impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> EwkbWrite
591    for EwkbGeometry<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
592where
593    P: 'a + postgis::Point,
594    PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
595    MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
596    L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
597    LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
598    ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
599    Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
600    YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
601    MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
602    G: 'a
603        + postgis::Geometry<
604            'a,
605            Point = P,
606            LineString = L,
607            Polygon = Y,
608            MultiPoint = MP,
609            MultiLineString = ML,
610            MultiPolygon = MY,
611            GeometryCollection = GC,
612        >,
613    GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
614    GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
615{
616    fn opt_srid(&self) -> Option<i32> {
617        match *self {
618            EwkbGeometry::Point(ref ewkb) => ewkb.opt_srid(),
619            EwkbGeometry::LineString(ref ewkb) => ewkb.opt_srid(),
620            EwkbGeometry::Polygon(ref ewkb) => ewkb.opt_srid(),
621            EwkbGeometry::MultiPoint(ref ewkb) => ewkb.opt_srid(),
622            EwkbGeometry::MultiLineString(ref ewkb) => ewkb.opt_srid(),
623            EwkbGeometry::MultiPolygon(ref ewkb) => ewkb.opt_srid(),
624            EwkbGeometry::GeometryCollection(ref ewkb) => ewkb.opt_srid(),
625        }
626    }
627
628    fn type_id(&self) -> u32 {
629        match *self {
630            EwkbGeometry::Point(ref ewkb) => ewkb.type_id(),
631            EwkbGeometry::LineString(ref ewkb) => ewkb.type_id(),
632            EwkbGeometry::Polygon(ref ewkb) => ewkb.type_id(),
633            EwkbGeometry::MultiPoint(ref ewkb) => ewkb.type_id(),
634            EwkbGeometry::MultiLineString(ref ewkb) => ewkb.type_id(),
635            EwkbGeometry::MultiPolygon(ref ewkb) => ewkb.type_id(),
636            EwkbGeometry::GeometryCollection(ref ewkb) => ewkb.type_id(),
637        }
638    }
639
640    fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
641        match *self {
642            EwkbGeometry::Point(ref ewkb) => ewkb.write_ewkb_body(w),
643            EwkbGeometry::LineString(ref ewkb) => ewkb.write_ewkb_body(w),
644            EwkbGeometry::Polygon(ref ewkb) => ewkb.write_ewkb_body(w),
645            EwkbGeometry::MultiPoint(ref ewkb) => ewkb.write_ewkb_body(w),
646            EwkbGeometry::MultiLineString(ref ewkb) => ewkb.write_ewkb_body(w),
647            EwkbGeometry::MultiPolygon(ref ewkb) => ewkb.write_ewkb_body(w),
648            EwkbGeometry::GeometryCollection(ref ewkb) => ewkb.write_ewkb_body(w),
649        }
650    }
651}
652
653impl<'a, P> AsEwkbGeometry<'a> for GeometryT<P>
654where
655    P: 'a + postgis::Point + EwkbRead + AsEwkbPoint<'a>,
656{
657    type PointType = P;
658    type PointIter = Iter<'a, P>;
659    type MultiPointType = MultiPointT<P>;
660    type LineType = LineStringT<P>;
661    type LineIter = Iter<'a, Self::LineType>;
662    type MultiLineType = MultiLineStringT<P>;
663    type PolyType = PolygonT<P>;
664    type PolyIter = Iter<'a, Self::PolyType>;
665    type MultiPolyType = MultiPolygonT<P>;
666    type GeomType = GeometryT<P>;
667    type GeomIter = Iter<'a, Self::GeomType>;
668    type GeomCollection = GeometryCollectionT<P>;
669    fn as_ewkb(
670        &'a self,
671    ) -> EwkbGeometry<
672        'a,
673        Self::PointType,
674        Self::PointIter,
675        Self::MultiPointType,
676        Self::LineType,
677        Self::LineIter,
678        Self::MultiLineType,
679        Self::PolyType,
680        Self::PolyIter,
681        Self::MultiPolyType,
682        Self::GeomType,
683        Self::GeomIter,
684        Self::GeomCollection,
685    > {
686        match *self {
687            GeometryT::Point(ref geom) => EwkbGeometry::Point(geom.as_ewkb()),
688            GeometryT::LineString(ref geom) => EwkbGeometry::LineString(geom.as_ewkb()),
689            GeometryT::Polygon(ref geom) => EwkbGeometry::Polygon(geom.as_ewkb()),
690            GeometryT::MultiPoint(ref geom) => EwkbGeometry::MultiPoint(geom.as_ewkb()),
691            GeometryT::MultiLineString(ref geom) => EwkbGeometry::MultiLineString(geom.as_ewkb()),
692            GeometryT::MultiPolygon(ref geom) => EwkbGeometry::MultiPolygon(geom.as_ewkb()),
693            GeometryT::GeometryCollection(ref geom) => {
694                EwkbGeometry::GeometryCollection(geom.as_ewkb())
695            }
696        }
697    }
698}
699
700/// OGC Geometry type
701pub type Geometry = GeometryT<Point>;
702/// OGC GeometryZ type
703pub type GeometryZ = GeometryT<PointZ>;
704/// OGC GeometryM type
705pub type GeometryM = GeometryT<PointM>;
706/// OGC GeometryZM type
707pub type GeometryZM = GeometryT<PointZM>;
708
709#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
710#[derive(Clone, Debug)]
711pub struct GeometryCollectionT<P: postgis::Point + EwkbRead> {
712    pub geometries: Vec<GeometryT<P>>,
713    pub srid: Option<i32>,
714}
715
716impl<P> Default for GeometryCollectionT<P>
717where
718    P: postgis::Point + EwkbRead,
719 {
720    fn default() -> Self {
721        Self::new()
722    }
723}
724
725impl<P> GeometryCollectionT<P>
726where
727    P: postgis::Point + EwkbRead,
728{
729    pub fn new() -> GeometryCollectionT<P> {
730        GeometryCollectionT {
731            geometries: Vec::new(),
732            srid: None,
733        }
734    }
735}
736
737impl<'a, P> postgis::GeometryCollection<'a> for GeometryCollectionT<P>
738where
739    P: 'a + postgis::Point + EwkbRead,
740{
741    type ItemType = GeometryT<P>;
742    type Iter = Iter<'a, Self::ItemType>;
743    fn geometries(&'a self) -> Self::Iter {
744        self.geometries.iter()
745    }
746}
747
748impl<P> EwkbRead for GeometryCollectionT<P>
749where
750    P: postgis::Point + EwkbRead,
751{
752    fn point_type() -> PointType {
753        P::point_type()
754    }
755
756    fn read_ewkb_body<R: Read>(
757        raw: &mut R,
758        is_be: bool,
759        _type_id: u32,
760        _srid: Option<i32>,
761    ) -> Result<Self, Error> {
762        let mut ret = GeometryCollectionT::new();
763        let size = read_u32(raw, is_be)? as usize;
764        for _ in 0..size {
765            let is_be = raw.read_i8()? == 0i8;
766
767            let type_id = read_u32(raw, is_be)?;
768            let mut srid: Option<i32> = None;
769            if type_id & 0x20000000 == 0x20000000 {
770                srid = Some(read_i32(raw, is_be)?);
771            }
772            let geom = match type_id & 0xff {
773                0x01 => GeometryT::Point(P::read_ewkb_body(raw, is_be, type_id, srid)?),
774                0x02 => GeometryT::LineString(LineStringT::<P>::read_ewkb_body(
775                    raw, is_be, type_id, srid,
776                )?),
777                0x03 => GeometryT::Polygon(PolygonT::read_ewkb_body(raw, is_be, type_id, srid)?),
778                0x04 => {
779                    GeometryT::MultiPoint(MultiPointT::read_ewkb_body(raw, is_be, type_id, srid)?)
780                }
781                0x05 => GeometryT::MultiLineString(MultiLineStringT::read_ewkb_body(
782                    raw, is_be, type_id, srid,
783                )?),
784                0x06 => GeometryT::MultiPolygon(MultiPolygonT::read_ewkb_body(
785                    raw, is_be, type_id, srid,
786                )?),
787                0x07 => GeometryT::GeometryCollection(GeometryCollectionT::read_ewkb_body(
788                    raw, is_be, type_id, srid,
789                )?),
790                _ => {
791                    return Err(Error::Read(format!(
792                        "Error reading generic geometry type - unsupported type id {}.",
793                        type_id
794                    )))
795                }
796            };
797            ret.geometries.push(geom);
798        }
799        Ok(ret)
800    }
801}
802
803pub struct EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
804where
805    P: 'a + postgis::Point,
806    PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
807    MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
808    L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
809    LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
810    ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
811    Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
812    YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
813    MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
814    G: 'a
815        + postgis::Geometry<
816            'a,
817            Point = P,
818            LineString = L,
819            Polygon = Y,
820            MultiPoint = MP,
821            MultiLineString = ML,
822            MultiPolygon = MY,
823            GeometryCollection = GC,
824        >,
825    GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
826    GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
827{
828    pub geom: &'a dyn postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
829    pub srid: Option<i32>,
830    pub point_type: PointType,
831}
832
833pub trait AsEwkbGeometryCollection<'a> {
834    type PointType: 'a + postgis::Point + EwkbRead;
835    type PointIter: Iterator<Item = &'a Self::PointType>
836        + ExactSizeIterator<Item = &'a Self::PointType>;
837    type MultiPointType: 'a
838        + postgis::MultiPoint<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
839    type LineType: 'a + postgis::LineString<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
840    type LineIter: Iterator<Item = &'a Self::LineType>
841        + ExactSizeIterator<Item = &'a Self::LineType>;
842    type MultiLineType: 'a
843        + postgis::MultiLineString<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
844    type PolyType: 'a + postgis::Polygon<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
845    type PolyIter: Iterator<Item = &'a Self::PolyType>
846        + ExactSizeIterator<Item = &'a Self::PolyType>;
847    type MultiPolyType: 'a
848        + postgis::MultiPolygon<'a, ItemType = Self::PolyType, Iter = Self::PolyIter>;
849    type GeomType: 'a
850        + postgis::Geometry<
851            'a,
852            Point = Self::PointType,
853            LineString = Self::LineType,
854            Polygon = Self::PolyType,
855            MultiPoint = Self::MultiPointType,
856            MultiLineString = Self::MultiLineType,
857            MultiPolygon = Self::MultiPolyType,
858            GeometryCollection = Self::GeomCollection,
859        >;
860    type GeomIter: Iterator<Item = &'a Self::GeomType>
861        + ExactSizeIterator<Item = &'a Self::GeomType>;
862    type GeomCollection: 'a
863        + postgis::GeometryCollection<'a, ItemType = Self::GeomType, Iter = Self::GeomIter>;
864    fn as_ewkb(
865        &'a self,
866    ) -> EwkbGeometryCollection<
867        'a,
868        Self::PointType,
869        Self::PointIter,
870        Self::MultiPointType,
871        Self::LineType,
872        Self::LineIter,
873        Self::MultiLineType,
874        Self::PolyType,
875        Self::PolyIter,
876        Self::MultiPolyType,
877        Self::GeomType,
878        Self::GeomIter,
879        Self::GeomCollection,
880    >;
881}
882
883impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> fmt::Debug
884    for EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
885where
886    P: 'a + postgis::Point,
887    PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
888    MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
889    L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
890    LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
891    ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
892    Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
893    YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
894    MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
895    G: 'a
896        + postgis::Geometry<
897            'a,
898            Point = P,
899            LineString = L,
900            Polygon = Y,
901            MultiPoint = MP,
902            MultiLineString = ML,
903            MultiPolygon = MY,
904            GeometryCollection = GC,
905        >,
906    GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
907    GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
908{
909    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
910        write!(f, stringify!(EwkbGeometryCollection))?; //TODO
911        Ok(())
912    }
913}
914
915impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> EwkbWrite
916    for EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
917where
918    P: 'a + postgis::Point,
919    PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
920    MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
921    L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
922    LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
923    ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
924    Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
925    YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
926    MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
927    G: 'a
928        + postgis::Geometry<
929            'a,
930            Point = P,
931            LineString = L,
932            Polygon = Y,
933            MultiPoint = MP,
934            MultiLineString = ML,
935            MultiPolygon = MY,
936            GeometryCollection = GC,
937        >,
938    GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
939    GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
940{
941    fn opt_srid(&self) -> Option<i32> {
942        self.srid
943    }
944
945    fn type_id(&self) -> u32 {
946        0x07 | Self::wkb_type_id(&self.point_type, self.srid)
947    }
948
949    fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
950        w.write_u32::<LittleEndian>(self.geom.geometries().len() as u32)?;
951
952        for geom in self.geom.geometries() {
953            match geom.as_type() {
954                postgis::GeometryType::Point(geom) => {
955                    let wkb = EwkbPoint {
956                        geom,
957                        srid: None,
958                        point_type: self.point_type,
959                    };
960                    wkb.write_ewkb(w)?;
961                }
962                postgis::GeometryType::LineString(geom) => {
963                    let wkb = EwkbLineString {
964                        geom,
965                        srid: None,
966                        point_type: self.point_type,
967                    };
968                    wkb.write_ewkb(w)?;
969                }
970                postgis::GeometryType::Polygon(geom) => {
971                    let wkb = EwkbPolygon {
972                        geom,
973                        srid: None,
974                        point_type: self.point_type,
975                    };
976                    wkb.write_ewkb(w)?;
977                }
978                postgis::GeometryType::MultiPoint(geom) => {
979                    let wkb = EwkbMultiPoint {
980                        geom,
981                        srid: None,
982                        point_type: self.point_type,
983                    };
984                    wkb.write_ewkb(w)?;
985                }
986                postgis::GeometryType::MultiLineString(geom) => {
987                    let wkb = EwkbMultiLineString {
988                        geom,
989                        srid: None,
990                        point_type: self.point_type,
991                    };
992                    wkb.write_ewkb(w)?;
993                }
994                postgis::GeometryType::MultiPolygon(geom) => {
995                    let wkb = EwkbMultiPolygon {
996                        geom,
997                        srid: None,
998                        point_type: self.point_type,
999                    };
1000                    wkb.write_ewkb(w)?;
1001                }
1002                postgis::GeometryType::GeometryCollection(geom) => {
1003                    let wkb = EwkbGeometryCollection {
1004                        geom,
1005                        srid: None,
1006                        point_type: self.point_type,
1007                    };
1008                    wkb.write_ewkb(w)?;
1009                }
1010            }
1011        }
1012        Ok(())
1013    }
1014}
1015
1016impl<'a, P> AsEwkbGeometryCollection<'a> for GeometryCollectionT<P>
1017where
1018    P: 'a + postgis::Point + EwkbRead,
1019{
1020    type PointType = P;
1021    type PointIter = Iter<'a, P>;
1022    type MultiPointType = MultiPointT<P>;
1023    type LineType = LineStringT<P>;
1024    type LineIter = Iter<'a, Self::LineType>;
1025    type MultiLineType = MultiLineStringT<P>;
1026    type PolyType = PolygonT<P>;
1027    type PolyIter = Iter<'a, Self::PolyType>;
1028    type MultiPolyType = MultiPolygonT<P>;
1029    type GeomType = GeometryT<P>;
1030    type GeomIter = Iter<'a, Self::GeomType>;
1031    type GeomCollection = GeometryCollectionT<P>;
1032    fn as_ewkb(
1033        &'a self,
1034    ) -> EwkbGeometryCollection<
1035        'a,
1036        Self::PointType,
1037        Self::PointIter,
1038        Self::MultiPointType,
1039        Self::LineType,
1040        Self::LineIter,
1041        Self::MultiLineType,
1042        Self::PolyType,
1043        Self::PolyIter,
1044        Self::MultiPolyType,
1045        Self::GeomType,
1046        Self::GeomIter,
1047        Self::GeomCollection,
1048    > {
1049        EwkbGeometryCollection {
1050            geom: self,
1051            srid: self.srid,
1052            point_type: P::point_type(),
1053        }
1054    }
1055}
1056
1057/// OGC GeometryCollection type
1058pub type GeometryCollection = GeometryCollectionT<Point>;
1059/// OGC GeometryCollectionZ type
1060pub type GeometryCollectionZ = GeometryCollectionT<PointZ>;
1061/// OGC GeometryCollectionM type
1062pub type GeometryCollectionM = GeometryCollectionT<PointM>;
1063/// OGC GeometryCollectionZM type
1064pub type GeometryCollectionZM = GeometryCollectionT<PointZM>;