1use crate::ewkb::*;
2
3macro_rules! geometry_container_type {
4 ($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))?; 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))?; 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
331pub type Polygon = PolygonT<Point>;
333pub type PolygonZ = PolygonT<PointZ>;
335pub type PolygonM = PolygonT<PointM>;
337pub 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
347pub type MultiLineString = MultiLineStringT<Point>;
349pub type MultiLineStringZ = MultiLineStringT<PointZ>;
351pub type MultiLineStringM = MultiLineStringT<PointM>;
353pub 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
363pub type MultiPolygon = MultiPolygonT<Point>;
365pub type MultiPolygonZ = MultiPolygonT<PointZ>;
367pub type MultiPolygonM = MultiPolygonT<PointM>;
369pub type MultiPolygonZM = MultiPolygonT<PointZM>;
371
372#[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))?; 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
700pub type Geometry = GeometryT<Point>;
702pub type GeometryZ = GeometryT<PointZ>;
704pub type GeometryM = GeometryT<PointM>;
706pub 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))?; 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
1057pub type GeometryCollection = GeometryCollectionT<Point>;
1059pub type GeometryCollectionZ = GeometryCollectionT<PointZ>;
1061pub type GeometryCollectionM = GeometryCollectionT<PointM>;
1063pub type GeometryCollectionZM = GeometryCollectionT<PointZM>;