1use crate::{error::Error, types as postgis};
9use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
10use std;
11use std::fmt;
12use std::io::prelude::*;
13use std::iter::FromIterator;
14use std::slice::Iter;
15
16#[derive(PartialEq, Clone, Copy, Debug)]
19pub struct Point {
20 pub x: f64,
21 pub y: f64,
22 pub srid: Option<i32>,
23}
24
25#[derive(PartialEq, Clone, Copy, Debug)]
26pub struct PointZ {
27 pub x: f64,
28 pub y: f64,
29 pub z: f64,
30 pub srid: Option<i32>,
31}
32
33#[derive(PartialEq, Clone, Copy, Debug)]
34pub struct PointM {
35 pub x: f64,
36 pub y: f64,
37 pub m: f64,
38 pub srid: Option<i32>,
39}
40
41#[derive(PartialEq, Clone, Copy, Debug)]
42pub struct PointZM {
43 pub x: f64,
44 pub y: f64,
45 pub z: f64,
46 pub m: f64,
47 pub srid: Option<i32>,
48}
49
50#[derive(PartialEq, Clone, Copy, Debug)]
51pub enum PointType {
52 Point,
53 PointZ,
54 PointM,
55 PointZM,
56}
57
58pub trait EwkbRead: fmt::Debug + Sized {
61 fn point_type() -> PointType;
62
63 fn read_ewkb<R: Read>(raw: &mut R) -> Result<Self, Error> {
64 let byte_order = raw.read_i8()?;
65 let is_be = byte_order == 0i8;
66
67 let type_id = read_u32(raw, is_be)?;
68 let mut srid: Option<i32> = None;
69 if type_id & 0x20000000 == 0x20000000 {
70 srid = Some(read_i32(raw, is_be)?);
71 }
72 Self::read_ewkb_body(raw, is_be, type_id, srid)
73 }
74
75 #[doc(hidden)]
76 fn read_ewkb_body<R: Read>(
77 raw: &mut R,
78 is_be: bool,
79 type_id: u32,
80 srid: Option<i32>,
81 ) -> Result<Self, Error>;
82}
83
84pub trait EwkbWrite: fmt::Debug + Sized {
85 fn opt_srid(&self) -> Option<i32> {
86 None
87 }
88
89 fn wkb_type_id(point_type: &PointType, srid: Option<i32>) -> u32 {
90 let mut type_ = 0;
91 if srid.is_some() {
92 type_ |= 0x20000000;
93 }
94 if *point_type == PointType::PointZ || *point_type == PointType::PointZM {
95 type_ |= 0x80000000;
96 }
97 if *point_type == PointType::PointM || *point_type == PointType::PointZM {
98 type_ |= 0x40000000;
99 }
100 type_
101 }
102
103 fn type_id(&self) -> u32;
104
105 fn write_ewkb<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
106 w.write_u8(0x01)?;
108 let type_id = self.type_id();
109 w.write_u32::<LittleEndian>(type_id)?;
110 self.opt_srid()
111 .map(|srid| w.write_i32::<LittleEndian>(srid));
112 self.write_ewkb_body(w)?;
113 Ok(())
114 }
115 #[doc(hidden)]
116 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error>;
117
118 fn to_hex_ewkb(&self) -> String {
119 let mut buf: Vec<u8> = Vec::new();
120 let _ = self.write_ewkb(&mut buf).unwrap();
121 let hex: String = buf
122 .iter()
123 .fold(String::new(), |s, &b| s + &format!("{:02X}", b));
124 hex
125 }
126}
127
128impl From<std::io::Error> for Error {
131 fn from(e: std::io::Error) -> Error {
132 Error::Read(format!("error while reading: {:?}", e))
133 }
134}
135
136fn read_u32<R: Read>(raw: &mut R, is_be: bool) -> Result<u32, Error> {
137 Ok(if is_be {
138 raw.read_u32::<BigEndian>()?
139 } else {
140 raw.read_u32::<LittleEndian>()?
141 })
142}
143
144fn read_i32<R: Read>(raw: &mut R, is_be: bool) -> Result<i32, Error> {
145 Ok(if is_be {
146 raw.read_i32::<BigEndian>()?
147 } else {
148 raw.read_i32::<LittleEndian>()?
149 })
150}
151
152fn read_f64<R: Read>(raw: &mut R, is_be: bool) -> Result<f64, Error> {
153 Ok(if is_be {
154 raw.read_f64::<BigEndian>()?
155 } else {
156 raw.read_f64::<LittleEndian>()?
157 })
158}
159
160fn has_z(type_id: u32) -> bool {
163 type_id & 0x80000000 == 0x80000000
164}
165fn has_m(type_id: u32) -> bool {
166 type_id & 0x40000000 == 0x40000000
167}
168
169impl Point {
170 pub fn new(x: f64, y: f64, srid: Option<i32>) -> Self {
171 Point {
172 x: x,
173 y: y,
174 srid: srid,
175 }
176 }
177 pub fn new_from_opt_vals(
178 x: f64,
179 y: f64,
180 _z: Option<f64>,
181 _m: Option<f64>,
182 srid: Option<i32>,
183 ) -> Self {
184 Self::new(x, y, srid)
185 }
186}
187
188impl postgis::Point for Point {
189 fn x(&self) -> f64 {
190 self.x
191 }
192 fn y(&self) -> f64 {
193 self.y
194 }
195}
196
197impl PointZ {
198 pub fn new(x: f64, y: f64, z: f64, srid: Option<i32>) -> Self {
199 PointZ {
200 x: x,
201 y: y,
202 z: z,
203 srid: srid,
204 }
205 }
206 pub fn new_from_opt_vals(
207 x: f64,
208 y: f64,
209 z: Option<f64>,
210 _m: Option<f64>,
211 srid: Option<i32>,
212 ) -> Self {
213 Self::new(x, y, z.unwrap(), srid)
214 }
215}
216
217impl postgis::Point for PointZ {
218 fn x(&self) -> f64 {
219 self.x
220 }
221 fn y(&self) -> f64 {
222 self.y
223 }
224 fn opt_z(&self) -> Option<f64> {
225 Some(self.z)
226 }
227}
228
229impl PointM {
230 pub fn new(x: f64, y: f64, m: f64, srid: Option<i32>) -> Self {
231 PointM {
232 x: x,
233 y: y,
234 m: m,
235 srid: srid,
236 }
237 }
238 pub fn new_from_opt_vals(
239 x: f64,
240 y: f64,
241 _z: Option<f64>,
242 m: Option<f64>,
243 srid: Option<i32>,
244 ) -> Self {
245 Self::new(x, y, m.unwrap(), srid)
246 }
247}
248
249impl postgis::Point for PointM {
250 fn x(&self) -> f64 {
251 self.x
252 }
253 fn y(&self) -> f64 {
254 self.y
255 }
256 fn opt_m(&self) -> Option<f64> {
257 Some(self.m)
258 }
259}
260
261impl PointZM {
262 pub fn new(x: f64, y: f64, z: f64, m: f64, srid: Option<i32>) -> Self {
263 PointZM {
264 x: x,
265 y: y,
266 z: z,
267 m: m,
268 srid: srid,
269 }
270 }
271 pub fn new_from_opt_vals(
272 x: f64,
273 y: f64,
274 z: Option<f64>,
275 m: Option<f64>,
276 srid: Option<i32>,
277 ) -> Self {
278 Self::new(x, y, z.unwrap(), m.unwrap(), srid)
279 }
280}
281
282impl postgis::Point for PointZM {
283 fn x(&self) -> f64 {
284 self.x
285 }
286 fn y(&self) -> f64 {
287 self.y
288 }
289 fn opt_z(&self) -> Option<f64> {
290 Some(self.z)
291 }
292 fn opt_m(&self) -> Option<f64> {
293 Some(self.m)
294 }
295}
296
297macro_rules! impl_point_read_traits {
298 ($ptype:ident) => {
299 impl EwkbRead for $ptype {
300 fn point_type() -> PointType {
301 PointType::$ptype
302 }
303 fn read_ewkb_body<R: Read>(
304 raw: &mut R,
305 is_be: bool,
306 type_id: u32,
307 srid: Option<i32>,
308 ) -> Result<Self, Error> {
309 let x = read_f64(raw, is_be)?;
310 let y = read_f64(raw, is_be)?;
311 let z = if has_z(type_id) {
312 Some(read_f64(raw, is_be)?)
313 } else {
314 None
315 };
316 let m = if has_m(type_id) {
317 Some(read_f64(raw, is_be)?)
318 } else {
319 None
320 };
321 Ok(Self::new_from_opt_vals(x, y, z, m, srid))
322 }
323 }
324
325 impl<'a> AsEwkbPoint<'a> for $ptype {
326 fn as_ewkb(&'a self) -> EwkbPoint<'a> {
327 EwkbPoint {
328 geom: self,
329 srid: self.srid,
330 point_type: PointType::$ptype,
331 }
332 }
333 }
334 };
335}
336
337impl_point_read_traits!(Point);
338impl_point_read_traits!(PointZ);
339impl_point_read_traits!(PointM);
340impl_point_read_traits!(PointZM);
341
342pub struct EwkbPoint<'a> {
343 pub geom: &'a dyn postgis::Point,
344 pub srid: Option<i32>,
345 pub point_type: PointType,
346}
347
348pub trait AsEwkbPoint<'a> {
349 fn as_ewkb(&'a self) -> EwkbPoint<'a>;
350}
351
352impl<'a> fmt::Debug for EwkbPoint<'a> {
353 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
354 write!(f, "EwkbPoint")?; Ok(())
356 }
357}
358
359impl<'a> EwkbWrite for EwkbPoint<'a> {
360 fn type_id(&self) -> u32 {
361 0x01 | Self::wkb_type_id(&self.point_type, self.srid)
362 }
363 fn opt_srid(&self) -> Option<i32> {
364 self.srid
365 }
366 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
367 w.write_f64::<LittleEndian>(self.geom.x())?;
368 w.write_f64::<LittleEndian>(self.geom.y())?;
369 self.geom.opt_z().map(|z| w.write_f64::<LittleEndian>(z));
370 self.geom.opt_m().map(|m| w.write_f64::<LittleEndian>(m));
371 Ok(())
372 }
373}
374
375macro_rules! point_container_type {
376 ($geotypetrait:ident for $geotype:ident) => {
378 #[derive(PartialEq, Clone, Debug)]
380 pub struct $geotype<P: postgis::Point + EwkbRead> {
381 pub points: Vec<P>,
382 pub srid: Option<i32>,
383 }
384
385 impl<P: postgis::Point + EwkbRead> $geotype<P> {
386 pub fn new() -> $geotype<P> {
387 $geotype {
388 points: Vec::new(),
389 srid: None,
390 }
391 }
392 }
393
394 impl<P> FromIterator<P> for $geotype<P>
395 where
396 P: postgis::Point + EwkbRead,
397 {
398 #[inline]
399 fn from_iter<I: IntoIterator<Item = P>>(iterable: I) -> $geotype<P> {
400 let iterator = iterable.into_iter();
401 let (lower, _) = iterator.size_hint();
402 let mut ret = $geotype::new();
403 ret.points.reserve(lower);
404 for item in iterator {
405 ret.points.push(item);
406 }
407 ret
408 }
409 }
410
411 impl<'a, P> postgis::$geotypetrait<'a> for $geotype<P>
412 where
413 P: 'a + postgis::Point + EwkbRead,
414 {
415 type ItemType = P;
416 type Iter = Iter<'a, Self::ItemType>;
417 fn points(&'a self) -> Self::Iter {
418 self.points.iter()
419 }
420 }
421 };
422}
423
424macro_rules! geometry_container_type {
425 ($geotypetrait:ident for $geotype:ident contains $itemtype:ident named $itemname:ident) => {
427 #[derive(PartialEq, Clone, Debug)]
428 pub struct $geotype<P: postgis::Point + EwkbRead> {
429 pub $itemname: Vec<$itemtype<P>>,
430 pub srid: Option<i32>,
431 }
432
433 impl<P> $geotype<P>
434 where
435 P: postgis::Point + EwkbRead,
436 {
437 pub fn new() -> $geotype<P> {
438 $geotype {
439 $itemname: Vec::new(),
440 srid: None,
441 }
442 }
443 }
444
445 impl<P> FromIterator<$itemtype<P>> for $geotype<P>
446 where
447 P: postgis::Point + EwkbRead,
448 {
449 #[inline]
450 fn from_iter<I: IntoIterator<Item = $itemtype<P>>>(iterable: I) -> $geotype<P> {
451 let iterator = iterable.into_iter();
452 let (lower, _) = iterator.size_hint();
453 let mut ret = $geotype::new();
454 ret.$itemname.reserve(lower);
455 for item in iterator {
456 ret.$itemname.push(item);
457 }
458 ret
459 }
460 }
461
462 impl<'a, P> postgis::$geotypetrait<'a> for $geotype<P>
463 where
464 P: 'a + postgis::Point + EwkbRead,
465 {
466 type ItemType = $itemtype<P>;
467 type Iter = Iter<'a, Self::ItemType>;
468 fn $itemname(&'a self) -> Self::Iter {
469 self.$itemname.iter()
470 }
471 }
472 };
473}
474
475macro_rules! impl_read_for_point_container_type {
476 (singletype $geotype:ident) => {
477 impl<P> EwkbRead for $geotype<P>
478 where
479 P: postgis::Point + EwkbRead,
480 {
481 fn point_type() -> PointType {
482 P::point_type()
483 }
484 fn read_ewkb_body<R: Read>(
485 raw: &mut R,
486 is_be: bool,
487 type_id: u32,
488 srid: Option<i32>,
489 ) -> Result<Self, Error> {
490 let mut points: Vec<P> = vec![];
491 let size = read_u32(raw, is_be)? as usize;
492 for _ in 0..size {
493 points.push(P::read_ewkb_body(raw, is_be, type_id, srid)?);
494 }
495 Ok($geotype::<P> {
496 points: points,
497 srid: srid,
498 })
499 }
500 }
501 };
502 (multitype $geotype:ident) => {
503 impl<P> EwkbRead for $geotype<P>
504 where
505 P: postgis::Point + EwkbRead,
506 {
507 fn point_type() -> PointType {
508 P::point_type()
509 }
510 fn read_ewkb_body<R: Read>(
511 raw: &mut R,
512 is_be: bool,
513 _type_id: u32,
514 srid: Option<i32>,
515 ) -> Result<Self, Error> {
516 let mut points: Vec<P> = vec![];
517 let size = read_u32(raw, is_be)? as usize;
518 for _ in 0..size {
519 points.push(P::read_ewkb(raw)?);
520 }
521 Ok($geotype::<P> {
522 points: points,
523 srid: srid,
524 })
525 }
526 }
527 };
528}
529
530macro_rules! impl_read_for_geometry_container_type {
531 (singletype $geotype:ident contains $itemtype:ident named $itemname:ident) => {
532 impl<P> EwkbRead for $geotype<P>
533 where
534 P: postgis::Point + EwkbRead,
535 {
536 fn point_type() -> PointType {
537 P::point_type()
538 }
539 fn read_ewkb_body<R: Read>(
540 raw: &mut R,
541 is_be: bool,
542 type_id: u32,
543 srid: Option<i32>,
544 ) -> Result<Self, Error> {
545 let mut $itemname: Vec<$itemtype<P>> = vec![];
546 let size = read_u32(raw, is_be)? as usize;
547 for _ in 0..size {
548 $itemname.push($itemtype::read_ewkb_body(raw, is_be, type_id, srid)?);
549 }
550 Ok($geotype::<P> {
551 $itemname: $itemname,
552 srid: srid,
553 })
554 }
555 }
556 };
557 (multitype $geotype:ident contains $itemtype:ident named $itemname:ident) => {
558 impl<P> EwkbRead for $geotype<P>
559 where
560 P: postgis::Point + EwkbRead,
561 {
562 fn point_type() -> PointType {
563 P::point_type()
564 }
565 fn read_ewkb_body<R: Read>(
566 raw: &mut R,
567 is_be: bool,
568 _type_id: u32,
569 srid: Option<i32>,
570 ) -> Result<Self, Error> {
571 let mut $itemname: Vec<$itemtype<P>> = vec![];
572 let size = read_u32(raw, is_be)? as usize;
573 for _ in 0..size {
574 $itemname.push($itemtype::read_ewkb(raw)?);
575 }
576 Ok($geotype::<P> {
577 $itemname: $itemname,
578 srid: srid,
579 })
580 }
581 }
582 };
583}
584
585macro_rules! point_container_write {
586 ($geotypetrait:ident and $asewkbtype:ident for $geotype:ident to $ewkbtype:ident with type code $typecode:expr, command $writecmd:ident) => {
587 pub struct $ewkbtype<'a, P, I>
588 where
589 P: 'a + postgis::Point,
590 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
591 {
592 pub geom: &'a dyn postgis::$geotypetrait<'a, ItemType = P, Iter = I>,
593 pub srid: Option<i32>,
594 pub point_type: PointType,
595 }
596
597 pub trait $asewkbtype<'a> {
598 type PointType: 'a + postgis::Point;
599 type Iter: Iterator<Item = &'a Self::PointType>
600 + ExactSizeIterator<Item = &'a Self::PointType>;
601 fn as_ewkb(&'a self) -> $ewkbtype<'a, Self::PointType, Self::Iter>;
602 }
603
604 impl<'a, T, I> fmt::Debug for $ewkbtype<'a, T, I>
605 where
606 T: 'a + postgis::Point,
607 I: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
608 {
609 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
610 write!(f, stringify!($ewkbtype))?; Ok(())
612 }
613 }
614
615 impl<'a, T, I> EwkbWrite for $ewkbtype<'a, T, I>
616 where
617 T: 'a + postgis::Point,
618 I: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
619 {
620 fn opt_srid(&self) -> Option<i32> {
621 self.srid
622 }
623
624 fn type_id(&self) -> u32 {
625 $typecode | Self::wkb_type_id(&self.point_type, self.srid)
626 }
627
628 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
629 w.write_u32::<LittleEndian>(self.geom.points().len() as u32)?;
630 for geom in self.geom.points() {
631 let wkb = EwkbPoint {
632 geom: geom,
633 srid: None,
634 point_type: self.point_type.clone(),
635 };
636 wkb.$writecmd(w)?;
637 }
638 Ok(())
639 }
640 }
641
642 impl<'a, P> $asewkbtype<'a> for $geotype<P>
643 where
644 P: 'a + postgis::Point + EwkbRead,
645 {
646 type PointType = P;
647 type Iter = Iter<'a, P>;
648 fn as_ewkb(&'a self) -> $ewkbtype<'a, Self::PointType, Self::Iter> {
649 $ewkbtype {
650 geom: self,
651 srid: self.srid,
652 point_type: Self::PointType::point_type(),
653 }
654 }
655 }
656 };
657}
658
659macro_rules! geometry_container_write {
660 ($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) => {
661 pub struct $ewkbtype<'a, P, I, T, J>
662 where
663 P: 'a + postgis::Point,
664 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
665 T: 'a + postgis::$itemtypetrait<'a, ItemType = P, Iter = I>,
666 J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
667 {
668 pub geom: &'a dyn postgis::$geotypetrait<'a, ItemType = T, Iter = J>,
669 pub srid: Option<i32>,
670 pub point_type: PointType,
671 }
672
673 pub trait $asewkbtype<'a> {
674 type PointType: 'a + postgis::Point;
675 type PointIter: Iterator<Item = &'a Self::PointType>
676 + ExactSizeIterator<Item = &'a Self::PointType>;
677 type ItemType: 'a
678 + postgis::$itemtypetrait<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
679 type Iter: Iterator<Item = &'a Self::ItemType>
680 + ExactSizeIterator<Item = &'a Self::ItemType>;
681 fn as_ewkb(
682 &'a self,
683 ) -> $ewkbtype<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter>;
684 }
685
686 impl<'a, P, I, T, J> fmt::Debug for $ewkbtype<'a, P, I, T, J>
687 where
688 P: 'a + postgis::Point,
689 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
690 T: 'a + postgis::$itemtypetrait<'a, ItemType = P, Iter = I>,
691 J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
692 {
693 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
694 write!(f, stringify!($ewkbtype))?; Ok(())
696 }
697 }
698
699 impl<'a, P, I, T, J> EwkbWrite for $ewkbtype<'a, P, I, T, J>
700 where
701 P: 'a + postgis::Point,
702 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
703 T: 'a + postgis::$itemtypetrait<'a, ItemType = P, Iter = I>,
704 J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
705 {
706 fn opt_srid(&self) -> Option<i32> {
707 self.srid
708 }
709
710 fn type_id(&self) -> u32 {
711 $typecode | Self::wkb_type_id(&self.point_type, self.srid)
712 }
713
714 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
715 w.write_u32::<LittleEndian>(self.geom.$itemname().len() as u32)?;
716 for geom in self.geom.$itemname() {
717 let wkb = $ewkbitemtype {
718 geom: geom,
719 srid: None,
720 point_type: self.point_type.clone(),
721 };
722 wkb.$writecmd(w)?;
723 }
724 Ok(())
725 }
726 }
727
728 impl<'a, P> $asewkbtype<'a> for $geotype<P>
729 where
730 P: 'a + postgis::Point + EwkbRead,
731 {
732 type PointType = P;
733 type PointIter = Iter<'a, P>;
734 type ItemType = $itemtype<P>;
735 type Iter = Iter<'a, Self::ItemType>;
736 fn as_ewkb(
737 &'a self,
738 ) -> $ewkbtype<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter> {
739 $ewkbtype {
740 geom: self,
741 srid: self.srid,
742 point_type: Self::PointType::point_type(),
743 }
744 }
745 }
746 };
747 (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) => {
748 pub struct $ewkbtype<'a, P, I, L, K, T, J>
749 where
750 P: 'a + postgis::Point,
751 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
752 L: 'a + postgis::LineString<'a, ItemType = P, Iter = I>,
753 K: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
754 T: 'a + postgis::$itemtypetrait<'a, ItemType = L, Iter = K>,
755 J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
756 {
757 pub geom: &'a dyn postgis::$geotypetrait<'a, ItemType = T, Iter = J>,
758 pub srid: Option<i32>,
759 pub point_type: PointType,
760 }
761
762 pub trait $asewkbtype<'a> {
763 type PointType: 'a + postgis::Point;
764 type PointIter: Iterator<Item = &'a Self::PointType>
765 + ExactSizeIterator<Item = &'a Self::PointType>;
766 type LineType: 'a
767 + postgis::LineString<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
768 type LineIter: Iterator<Item = &'a Self::LineType>
769 + ExactSizeIterator<Item = &'a Self::LineType>;
770 type ItemType: 'a
771 + postgis::$itemtypetrait<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
772 type Iter: Iterator<Item = &'a Self::ItemType>
773 + ExactSizeIterator<Item = &'a Self::ItemType>;
774 fn as_ewkb(
775 &'a self,
776 ) -> $ewkbtype<
777 'a,
778 Self::PointType,
779 Self::PointIter,
780 Self::LineType,
781 Self::LineIter,
782 Self::ItemType,
783 Self::Iter,
784 >;
785 }
786
787 impl<'a, P, I, L, K, T, J> fmt::Debug for $ewkbtype<'a, P, I, L, K, T, J>
788 where
789 P: 'a + postgis::Point,
790 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
791 L: 'a + postgis::LineString<'a, ItemType = P, Iter = I>,
792 K: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
793 T: 'a + postgis::$itemtypetrait<'a, ItemType = L, Iter = K>,
794 J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
795 {
796 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
797 write!(f, stringify!($ewkbtype))?; Ok(())
799 }
800 }
801
802 impl<'a, P, I, L, K, T, J> EwkbWrite for $ewkbtype<'a, P, I, L, K, T, J>
803 where
804 P: 'a + postgis::Point,
805 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
806 L: 'a + postgis::LineString<'a, ItemType = P, Iter = I>,
807 K: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
808 T: 'a + postgis::$itemtypetrait<'a, ItemType = L, Iter = K>,
809 J: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
810 {
811 fn opt_srid(&self) -> Option<i32> {
812 self.srid
813 }
814
815 fn type_id(&self) -> u32 {
816 $typecode | Self::wkb_type_id(&self.point_type, self.srid)
817 }
818
819 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
820 w.write_u32::<LittleEndian>(self.geom.$itemname().len() as u32)?;
821 for geom in self.geom.$itemname() {
822 let wkb = $ewkbitemtype {
823 geom: geom,
824 srid: None,
825 point_type: self.point_type.clone(),
826 };
827 wkb.$writecmd(w)?;
828 }
829 Ok(())
830 }
831 }
832
833 impl<'a, P> $asewkbtype<'a> for $geotype<P>
834 where
835 P: 'a + postgis::Point + EwkbRead,
836 {
837 type PointType = P;
838 type PointIter = Iter<'a, P>;
839 type LineType = LineStringT<P>;
840 type LineIter = Iter<'a, Self::LineType>;
841 type ItemType = $itemtype<P>;
842 type Iter = Iter<'a, Self::ItemType>;
843 fn as_ewkb(
844 &'a self,
845 ) -> $ewkbtype<
846 'a,
847 Self::PointType,
848 Self::PointIter,
849 Self::LineType,
850 Self::LineIter,
851 Self::ItemType,
852 Self::Iter,
853 > {
854 $ewkbtype {
855 geom: self,
856 srid: self.srid,
857 point_type: Self::PointType::point_type(),
858 }
859 }
860 }
861 };
862}
863
864point_container_type!(LineString for LineStringT);
865impl_read_for_point_container_type!(singletype LineStringT);
866point_container_write!(LineString and AsEwkbLineString for LineStringT
867 to EwkbLineString with type code 0x02,
868 command write_ewkb_body);
869
870pub type LineString = LineStringT<Point>;
872pub type LineStringZ = LineStringT<PointZ>;
874pub type LineStringM = LineStringT<PointM>;
876pub type LineStringZM = LineStringT<PointZM>;
878
879geometry_container_type!(Polygon for PolygonT contains LineStringT named rings);
880impl_read_for_geometry_container_type!(singletype PolygonT contains LineStringT named rings);
881geometry_container_write!(Polygon and AsEwkbPolygon for PolygonT
882 to EwkbPolygon with type code 0x03,
883 contains EwkbLineString,LineStringT as LineString named rings,
884 command write_ewkb_body);
885
886pub type Polygon = PolygonT<Point>;
888pub type PolygonZ = PolygonT<PointZ>;
890pub type PolygonM = PolygonT<PointM>;
892pub type PolygonZM = PolygonT<PointZM>;
894
895point_container_type!(MultiPoint for MultiPointT);
896impl_read_for_point_container_type!(multitype MultiPointT);
897point_container_write!(MultiPoint and AsEwkbMultiPoint for MultiPointT
898 to EwkbMultiPoint with type code 0x04,
899 command write_ewkb);
900
901pub type MultiPoint = MultiPointT<Point>;
903pub type MultiPointZ = MultiPointT<PointZ>;
905pub type MultiPointM = MultiPointT<PointM>;
907pub type MultiPointZM = MultiPointT<PointZM>;
909
910geometry_container_type!(MultiLineString for MultiLineStringT contains LineStringT named lines);
911impl_read_for_geometry_container_type!(multitype MultiLineStringT contains LineStringT named lines);
912geometry_container_write!(MultiLineString and AsEwkbMultiLineString for MultiLineStringT
913 to EwkbMultiLineString with type code 0x05,
914 contains EwkbLineString,LineStringT as LineString named lines,
915 command write_ewkb);
916
917pub type MultiLineString = MultiLineStringT<Point>;
919pub type MultiLineStringZ = MultiLineStringT<PointZ>;
921pub type MultiLineStringM = MultiLineStringT<PointM>;
923pub type MultiLineStringZM = MultiLineStringT<PointZM>;
925
926geometry_container_type!(MultiPolygon for MultiPolygonT contains PolygonT named polygons);
927impl_read_for_geometry_container_type!(multitype MultiPolygonT contains PolygonT named polygons);
928geometry_container_write!(multipoly MultiPolygon and AsEwkbMultiPolygon for MultiPolygonT
929 to EwkbMultiPolygon with type code 0x06,
930 contains EwkbPolygon,PolygonT as Polygon named polygons,
931 command write_ewkb);
932
933pub type MultiPolygon = MultiPolygonT<Point>;
935pub type MultiPolygonZ = MultiPolygonT<PointZ>;
937pub type MultiPolygonM = MultiPolygonT<PointM>;
939pub type MultiPolygonZM = MultiPolygonT<PointZM>;
941
942#[derive(Clone, Debug)]
944pub enum GeometryT<P: postgis::Point + EwkbRead> {
945 Point(P),
946 LineString(LineStringT<P>),
947 Polygon(PolygonT<P>),
948 MultiPoint(MultiPointT<P>),
949 MultiLineString(MultiLineStringT<P>),
950 MultiPolygon(MultiPolygonT<P>),
951 GeometryCollection(GeometryCollectionT<P>),
952}
953
954impl<'a, P> postgis::Geometry<'a> for GeometryT<P>
955where
956 P: 'a + postgis::Point + EwkbRead,
957{
958 type Point = P;
959 type LineString = LineStringT<P>;
960 type Polygon = PolygonT<P>;
961 type MultiPoint = MultiPointT<P>;
962 type MultiLineString = MultiLineStringT<P>;
963 type MultiPolygon = MultiPolygonT<P>;
964 type GeometryCollection = GeometryCollectionT<P>;
965 fn as_type(
966 &'a self,
967 ) -> postgis::GeometryType<
968 'a,
969 P,
970 LineStringT<P>,
971 PolygonT<P>,
972 MultiPointT<P>,
973 MultiLineStringT<P>,
974 MultiPolygonT<P>,
975 GeometryCollectionT<P>,
976 > {
977 use crate::ewkb::GeometryT as A;
978 use crate::types::GeometryType as B;
979 match *self {
980 A::Point(ref geom) => B::Point(geom),
981 A::LineString(ref geom) => B::LineString(geom),
982 A::Polygon(ref geom) => B::Polygon(geom),
983 A::MultiPoint(ref geom) => B::MultiPoint(geom),
984 A::MultiLineString(ref geom) => B::MultiLineString(geom),
985 A::MultiPolygon(ref geom) => B::MultiPolygon(geom),
986 A::GeometryCollection(ref geom) => B::GeometryCollection(geom),
987 }
988 }
989}
990
991impl<P> EwkbRead for GeometryT<P>
992where
993 P: postgis::Point + EwkbRead,
994{
995 fn point_type() -> PointType {
996 P::point_type()
997 }
998 fn read_ewkb<R: Read>(raw: &mut R) -> Result<Self, Error> {
999 let byte_order = raw.read_i8()?;
1000 let is_be = byte_order == 0i8;
1001
1002 let type_id = read_u32(raw, is_be)?;
1003 let mut srid: Option<i32> = None;
1004 if type_id & 0x20000000 == 0x20000000 {
1005 srid = Some(read_i32(raw, is_be)?);
1006 }
1007
1008 let geom = match type_id & 0xff {
1009 0x01 => GeometryT::Point(P::read_ewkb_body(raw, is_be, type_id, srid)?),
1010 0x02 => {
1011 GeometryT::LineString(LineStringT::<P>::read_ewkb_body(raw, is_be, type_id, srid)?)
1012 }
1013 0x03 => GeometryT::Polygon(PolygonT::read_ewkb_body(raw, is_be, type_id, srid)?),
1014 0x04 => GeometryT::MultiPoint(MultiPointT::read_ewkb_body(raw, is_be, type_id, srid)?),
1015 0x05 => GeometryT::MultiLineString(MultiLineStringT::read_ewkb_body(
1016 raw, is_be, type_id, srid,
1017 )?),
1018 0x06 => {
1019 GeometryT::MultiPolygon(MultiPolygonT::read_ewkb_body(raw, is_be, type_id, srid)?)
1020 }
1021 0x07 => GeometryT::GeometryCollection(GeometryCollectionT::read_ewkb_body(
1022 raw, is_be, type_id, srid,
1023 )?),
1024 _ => {
1025 return Err(Error::Read(format!(
1026 "Error reading generic geometry type - unsupported type id {}.",
1027 type_id
1028 )))
1029 }
1030 };
1031 Ok(geom)
1032 }
1033 fn read_ewkb_body<R: Read>(
1034 _raw: &mut R,
1035 _is_be: bool,
1036 _type_id: u32,
1037 _srid: Option<i32>,
1038 ) -> Result<Self, Error> {
1039 panic!("Not used for generic geometry type")
1040 }
1041}
1042
1043pub enum EwkbGeometry<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
1044where
1045 P: 'a + postgis::Point,
1046 PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
1047 MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
1048 L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
1049 LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
1050 ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
1051 Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
1052 YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
1053 MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
1054 G: 'a
1055 + postgis::Geometry<
1056 'a,
1057 Point = P,
1058 LineString = L,
1059 Polygon = Y,
1060 MultiPoint = MP,
1061 MultiLineString = ML,
1062 MultiPolygon = MY,
1063 GeometryCollection = GC,
1064 >,
1065 GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
1066 GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1067{
1068 Point(EwkbPoint<'a>),
1069 LineString(EwkbLineString<'a, P, PI>),
1070 Polygon(EwkbPolygon<'a, P, PI, L, LI>),
1071 MultiPoint(EwkbMultiPoint<'a, P, PI>),
1072 MultiLineString(EwkbMultiLineString<'a, P, PI, L, LI>),
1073 MultiPolygon(EwkbMultiPolygon<'a, P, PI, L, LI, Y, YI>),
1074 GeometryCollection(EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>),
1075}
1076
1077pub trait AsEwkbGeometry<'a> {
1078 type PointType: 'a + postgis::Point + EwkbRead;
1079 type PointIter: Iterator<Item = &'a Self::PointType>
1080 + ExactSizeIterator<Item = &'a Self::PointType>;
1081 type MultiPointType: 'a
1082 + postgis::MultiPoint<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
1083 type LineType: 'a + postgis::LineString<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
1084 type LineIter: Iterator<Item = &'a Self::LineType>
1085 + ExactSizeIterator<Item = &'a Self::LineType>;
1086 type MultiLineType: 'a
1087 + postgis::MultiLineString<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
1088 type PolyType: 'a + postgis::Polygon<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
1089 type PolyIter: Iterator<Item = &'a Self::PolyType>
1090 + ExactSizeIterator<Item = &'a Self::PolyType>;
1091 type MultiPolyType: 'a
1092 + postgis::MultiPolygon<'a, ItemType = Self::PolyType, Iter = Self::PolyIter>;
1093 type GeomType: 'a
1094 + postgis::Geometry<
1095 'a,
1096 Point = Self::PointType,
1097 LineString = Self::LineType,
1098 Polygon = Self::PolyType,
1099 MultiPoint = Self::MultiPointType,
1100 MultiLineString = Self::MultiLineType,
1101 MultiPolygon = Self::MultiPolyType,
1102 GeometryCollection = Self::GeomCollection,
1103 >;
1104 type GeomIter: Iterator<Item = &'a Self::GeomType>
1105 + ExactSizeIterator<Item = &'a Self::GeomType>;
1106 type GeomCollection: 'a
1107 + postgis::GeometryCollection<'a, ItemType = Self::GeomType, Iter = Self::GeomIter>;
1108 fn as_ewkb(
1109 &'a self,
1110 ) -> EwkbGeometry<
1111 'a,
1112 Self::PointType,
1113 Self::PointIter,
1114 Self::MultiPointType,
1115 Self::LineType,
1116 Self::LineIter,
1117 Self::MultiLineType,
1118 Self::PolyType,
1119 Self::PolyIter,
1120 Self::MultiPolyType,
1121 Self::GeomType,
1122 Self::GeomIter,
1123 Self::GeomCollection,
1124 >;
1125}
1126
1127impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> fmt::Debug
1128 for EwkbGeometry<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
1129where
1130 P: 'a + postgis::Point,
1131 PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
1132 MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
1133 L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
1134 LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
1135 ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
1136 Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
1137 YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
1138 MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
1139 G: 'a
1140 + postgis::Geometry<
1141 'a,
1142 Point = P,
1143 LineString = L,
1144 Polygon = Y,
1145 MultiPoint = MP,
1146 MultiLineString = ML,
1147 MultiPolygon = MY,
1148 GeometryCollection = GC,
1149 >,
1150 GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
1151 GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1152{
1153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1154 write!(f, stringify!(EwkbGeometry))?; Ok(())
1156 }
1157}
1158
1159impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> EwkbWrite
1160 for EwkbGeometry<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
1161where
1162 P: 'a + postgis::Point,
1163 PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
1164 MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
1165 L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
1166 LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
1167 ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
1168 Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
1169 YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
1170 MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
1171 G: 'a
1172 + postgis::Geometry<
1173 'a,
1174 Point = P,
1175 LineString = L,
1176 Polygon = Y,
1177 MultiPoint = MP,
1178 MultiLineString = ML,
1179 MultiPolygon = MY,
1180 GeometryCollection = GC,
1181 >,
1182 GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
1183 GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1184{
1185 fn opt_srid(&self) -> Option<i32> {
1186 match *self {
1187 EwkbGeometry::Point(ref ewkb) => ewkb.opt_srid(),
1188 EwkbGeometry::LineString(ref ewkb) => ewkb.opt_srid(),
1189 EwkbGeometry::Polygon(ref ewkb) => ewkb.opt_srid(),
1190 EwkbGeometry::MultiPoint(ref ewkb) => ewkb.opt_srid(),
1191 EwkbGeometry::MultiLineString(ref ewkb) => ewkb.opt_srid(),
1192 EwkbGeometry::MultiPolygon(ref ewkb) => ewkb.opt_srid(),
1193 EwkbGeometry::GeometryCollection(ref ewkb) => ewkb.opt_srid(),
1194 }
1195 }
1196
1197 fn type_id(&self) -> u32 {
1198 match *self {
1199 EwkbGeometry::Point(ref ewkb) => ewkb.type_id(),
1200 EwkbGeometry::LineString(ref ewkb) => ewkb.type_id(),
1201 EwkbGeometry::Polygon(ref ewkb) => ewkb.type_id(),
1202 EwkbGeometry::MultiPoint(ref ewkb) => ewkb.type_id(),
1203 EwkbGeometry::MultiLineString(ref ewkb) => ewkb.type_id(),
1204 EwkbGeometry::MultiPolygon(ref ewkb) => ewkb.type_id(),
1205 EwkbGeometry::GeometryCollection(ref ewkb) => ewkb.type_id(),
1206 }
1207 }
1208
1209 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
1210 match *self {
1211 EwkbGeometry::Point(ref ewkb) => ewkb.write_ewkb_body(w),
1212 EwkbGeometry::LineString(ref ewkb) => ewkb.write_ewkb_body(w),
1213 EwkbGeometry::Polygon(ref ewkb) => ewkb.write_ewkb_body(w),
1214 EwkbGeometry::MultiPoint(ref ewkb) => ewkb.write_ewkb_body(w),
1215 EwkbGeometry::MultiLineString(ref ewkb) => ewkb.write_ewkb_body(w),
1216 EwkbGeometry::MultiPolygon(ref ewkb) => ewkb.write_ewkb_body(w),
1217 EwkbGeometry::GeometryCollection(ref ewkb) => ewkb.write_ewkb_body(w),
1218 }
1219 }
1220}
1221
1222impl<'a, P> AsEwkbGeometry<'a> for GeometryT<P>
1223where
1224 P: 'a + postgis::Point + EwkbRead + AsEwkbPoint<'a>,
1225{
1226 type PointType = P;
1227 type PointIter = Iter<'a, P>;
1228 type MultiPointType = MultiPointT<P>;
1229 type LineType = LineStringT<P>;
1230 type LineIter = Iter<'a, Self::LineType>;
1231 type MultiLineType = MultiLineStringT<P>;
1232 type PolyType = PolygonT<P>;
1233 type PolyIter = Iter<'a, Self::PolyType>;
1234 type MultiPolyType = MultiPolygonT<P>;
1235 type GeomType = GeometryT<P>;
1236 type GeomIter = Iter<'a, Self::GeomType>;
1237 type GeomCollection = GeometryCollectionT<P>;
1238 fn as_ewkb(
1239 &'a self,
1240 ) -> EwkbGeometry<
1241 'a,
1242 Self::PointType,
1243 Self::PointIter,
1244 Self::MultiPointType,
1245 Self::LineType,
1246 Self::LineIter,
1247 Self::MultiLineType,
1248 Self::PolyType,
1249 Self::PolyIter,
1250 Self::MultiPolyType,
1251 Self::GeomType,
1252 Self::GeomIter,
1253 Self::GeomCollection,
1254 > {
1255 match *self {
1256 GeometryT::Point(ref geom) => EwkbGeometry::Point(geom.as_ewkb()),
1257 GeometryT::LineString(ref geom) => EwkbGeometry::LineString(geom.as_ewkb()),
1258 GeometryT::Polygon(ref geom) => EwkbGeometry::Polygon(geom.as_ewkb()),
1259 GeometryT::MultiPoint(ref geom) => EwkbGeometry::MultiPoint(geom.as_ewkb()),
1260 GeometryT::MultiLineString(ref geom) => EwkbGeometry::MultiLineString(geom.as_ewkb()),
1261 GeometryT::MultiPolygon(ref geom) => EwkbGeometry::MultiPolygon(geom.as_ewkb()),
1262 GeometryT::GeometryCollection(ref geom) => {
1263 EwkbGeometry::GeometryCollection(geom.as_ewkb())
1264 }
1265 }
1266 }
1267}
1268
1269pub type Geometry = GeometryT<Point>;
1271pub type GeometryZ = GeometryT<PointZ>;
1273pub type GeometryM = GeometryT<PointM>;
1275pub type GeometryZM = GeometryT<PointZM>;
1277
1278#[derive(Clone, Debug)]
1279pub struct GeometryCollectionT<P: postgis::Point + EwkbRead> {
1280 pub geometries: Vec<GeometryT<P>>,
1281 pub srid: Option<i32>,
1282}
1283
1284impl<P> GeometryCollectionT<P>
1285where
1286 P: postgis::Point + EwkbRead,
1287{
1288 pub fn new() -> GeometryCollectionT<P> {
1289 GeometryCollectionT {
1290 geometries: Vec::new(),
1291 srid: None,
1292 }
1293 }
1294}
1295
1296impl<'a, P> postgis::GeometryCollection<'a> for GeometryCollectionT<P>
1297where
1298 P: 'a + postgis::Point + EwkbRead,
1299{
1300 type ItemType = GeometryT<P>;
1301 type Iter = Iter<'a, Self::ItemType>;
1302 fn geometries(&'a self) -> Self::Iter {
1303 self.geometries.iter()
1304 }
1305}
1306
1307impl<P> EwkbRead for GeometryCollectionT<P>
1308where
1309 P: postgis::Point + EwkbRead,
1310{
1311 fn point_type() -> PointType {
1312 P::point_type()
1313 }
1314
1315 fn read_ewkb_body<R: Read>(
1316 raw: &mut R,
1317 is_be: bool,
1318 _type_id: u32,
1319 _srid: Option<i32>,
1320 ) -> Result<Self, Error> {
1321 let mut ret = GeometryCollectionT::new();
1322 let size = read_u32(raw, is_be)? as usize;
1323 for _ in 0..size {
1324 let is_be = raw.read_i8()? == 0i8;
1325
1326 let type_id = read_u32(raw, is_be)?;
1327 let mut srid: Option<i32> = None;
1328 if type_id & 0x20000000 == 0x20000000 {
1329 srid = Some(read_i32(raw, is_be)?);
1330 }
1331 let geom = match type_id & 0xff {
1332 0x01 => GeometryT::Point(P::read_ewkb_body(raw, is_be, type_id, srid)?),
1333 0x02 => GeometryT::LineString(LineStringT::<P>::read_ewkb_body(
1334 raw, is_be, type_id, srid,
1335 )?),
1336 0x03 => GeometryT::Polygon(PolygonT::read_ewkb_body(raw, is_be, type_id, srid)?),
1337 0x04 => {
1338 GeometryT::MultiPoint(MultiPointT::read_ewkb_body(raw, is_be, type_id, srid)?)
1339 }
1340 0x05 => GeometryT::MultiLineString(MultiLineStringT::read_ewkb_body(
1341 raw, is_be, type_id, srid,
1342 )?),
1343 0x06 => GeometryT::MultiPolygon(MultiPolygonT::read_ewkb_body(
1344 raw, is_be, type_id, srid,
1345 )?),
1346 0x07 => GeometryT::GeometryCollection(GeometryCollectionT::read_ewkb_body(
1347 raw, is_be, type_id, srid,
1348 )?),
1349 _ => {
1350 return Err(Error::Read(format!(
1351 "Error reading generic geometry type - unsupported type id {}.",
1352 type_id
1353 )))
1354 }
1355 };
1356 ret.geometries.push(geom);
1357 }
1358 Ok(ret)
1359 }
1360}
1361
1362pub struct EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
1363where
1364 P: 'a + postgis::Point,
1365 PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
1366 MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
1367 L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
1368 LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
1369 ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
1370 Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
1371 YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
1372 MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
1373 G: 'a
1374 + postgis::Geometry<
1375 'a,
1376 Point = P,
1377 LineString = L,
1378 Polygon = Y,
1379 MultiPoint = MP,
1380 MultiLineString = ML,
1381 MultiPolygon = MY,
1382 GeometryCollection = GC,
1383 >,
1384 GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
1385 GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1386{
1387 pub geom: &'a dyn postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1388 pub srid: Option<i32>,
1389 pub point_type: PointType,
1390}
1391
1392pub trait AsEwkbGeometryCollection<'a> {
1393 type PointType: 'a + postgis::Point + EwkbRead;
1394 type PointIter: Iterator<Item = &'a Self::PointType>
1395 + ExactSizeIterator<Item = &'a Self::PointType>;
1396 type MultiPointType: 'a
1397 + postgis::MultiPoint<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
1398 type LineType: 'a + postgis::LineString<'a, ItemType = Self::PointType, Iter = Self::PointIter>;
1399 type LineIter: Iterator<Item = &'a Self::LineType>
1400 + ExactSizeIterator<Item = &'a Self::LineType>;
1401 type MultiLineType: 'a
1402 + postgis::MultiLineString<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
1403 type PolyType: 'a + postgis::Polygon<'a, ItemType = Self::LineType, Iter = Self::LineIter>;
1404 type PolyIter: Iterator<Item = &'a Self::PolyType>
1405 + ExactSizeIterator<Item = &'a Self::PolyType>;
1406 type MultiPolyType: 'a
1407 + postgis::MultiPolygon<'a, ItemType = Self::PolyType, Iter = Self::PolyIter>;
1408 type GeomType: 'a
1409 + postgis::Geometry<
1410 'a,
1411 Point = Self::PointType,
1412 LineString = Self::LineType,
1413 Polygon = Self::PolyType,
1414 MultiPoint = Self::MultiPointType,
1415 MultiLineString = Self::MultiLineType,
1416 MultiPolygon = Self::MultiPolyType,
1417 GeometryCollection = Self::GeomCollection,
1418 >;
1419 type GeomIter: Iterator<Item = &'a Self::GeomType>
1420 + ExactSizeIterator<Item = &'a Self::GeomType>;
1421 type GeomCollection: 'a
1422 + postgis::GeometryCollection<'a, ItemType = Self::GeomType, Iter = Self::GeomIter>;
1423 fn as_ewkb(
1424 &'a self,
1425 ) -> EwkbGeometryCollection<
1426 'a,
1427 Self::PointType,
1428 Self::PointIter,
1429 Self::MultiPointType,
1430 Self::LineType,
1431 Self::LineIter,
1432 Self::MultiLineType,
1433 Self::PolyType,
1434 Self::PolyIter,
1435 Self::MultiPolyType,
1436 Self::GeomType,
1437 Self::GeomIter,
1438 Self::GeomCollection,
1439 >;
1440}
1441
1442impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> fmt::Debug
1443 for EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
1444where
1445 P: 'a + postgis::Point,
1446 PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
1447 MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
1448 L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
1449 LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
1450 ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
1451 Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
1452 YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
1453 MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
1454 G: 'a
1455 + postgis::Geometry<
1456 'a,
1457 Point = P,
1458 LineString = L,
1459 Polygon = Y,
1460 MultiPoint = MP,
1461 MultiLineString = ML,
1462 MultiPolygon = MY,
1463 GeometryCollection = GC,
1464 >,
1465 GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
1466 GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1467{
1468 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1469 write!(f, stringify!(EwkbGeometryCollection))?; Ok(())
1471 }
1472}
1473
1474impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> EwkbWrite
1475 for EwkbGeometryCollection<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC>
1476where
1477 P: 'a + postgis::Point,
1478 PI: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
1479 MP: 'a + postgis::MultiPoint<'a, ItemType = P, Iter = PI>,
1480 L: 'a + postgis::LineString<'a, ItemType = P, Iter = PI>,
1481 LI: 'a + Iterator<Item = &'a L> + ExactSizeIterator<Item = &'a L>,
1482 ML: 'a + postgis::MultiLineString<'a, ItemType = L, Iter = LI>,
1483 Y: 'a + postgis::Polygon<'a, ItemType = L, Iter = LI>,
1484 YI: 'a + Iterator<Item = &'a Y> + ExactSizeIterator<Item = &'a Y>,
1485 MY: 'a + postgis::MultiPolygon<'a, ItemType = Y, Iter = YI>,
1486 G: 'a
1487 + postgis::Geometry<
1488 'a,
1489 Point = P,
1490 LineString = L,
1491 Polygon = Y,
1492 MultiPoint = MP,
1493 MultiLineString = ML,
1494 MultiPolygon = MY,
1495 GeometryCollection = GC,
1496 >,
1497 GI: 'a + Iterator<Item = &'a G> + ExactSizeIterator<Item = &'a G>,
1498 GC: 'a + postgis::GeometryCollection<'a, ItemType = G, Iter = GI>,
1499{
1500 fn opt_srid(&self) -> Option<i32> {
1501 self.srid
1502 }
1503
1504 fn type_id(&self) -> u32 {
1505 0x07 | Self::wkb_type_id(&self.point_type, self.srid)
1506 }
1507
1508 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
1509 w.write_u32::<LittleEndian>(self.geom.geometries().len() as u32)?;
1510
1511 for geom in self.geom.geometries() {
1512 match geom.as_type() {
1513 postgis::GeometryType::Point(geom) => {
1514 let wkb = EwkbPoint {
1515 geom: geom,
1516 srid: None,
1517 point_type: self.point_type.clone(),
1518 };
1519 wkb.write_ewkb(w)?;
1520 }
1521 postgis::GeometryType::LineString(geom) => {
1522 let wkb = EwkbLineString {
1523 geom: geom,
1524 srid: None,
1525 point_type: self.point_type.clone(),
1526 };
1527 wkb.write_ewkb(w)?;
1528 }
1529 postgis::GeometryType::Polygon(geom) => {
1530 let wkb = EwkbPolygon {
1531 geom: geom,
1532 srid: None,
1533 point_type: self.point_type.clone(),
1534 };
1535 wkb.write_ewkb(w)?;
1536 }
1537 postgis::GeometryType::MultiPoint(geom) => {
1538 let wkb = EwkbMultiPoint {
1539 geom: geom,
1540 srid: None,
1541 point_type: self.point_type.clone(),
1542 };
1543 wkb.write_ewkb(w)?;
1544 }
1545 postgis::GeometryType::MultiLineString(geom) => {
1546 let wkb = EwkbMultiLineString {
1547 geom: geom,
1548 srid: None,
1549 point_type: self.point_type.clone(),
1550 };
1551 wkb.write_ewkb(w)?;
1552 }
1553 postgis::GeometryType::MultiPolygon(geom) => {
1554 let wkb = EwkbMultiPolygon {
1555 geom: geom,
1556 srid: None,
1557 point_type: self.point_type.clone(),
1558 };
1559 wkb.write_ewkb(w)?;
1560 }
1561 postgis::GeometryType::GeometryCollection(geom) => {
1562 let wkb = EwkbGeometryCollection {
1563 geom: geom,
1564 srid: None,
1565 point_type: self.point_type.clone(),
1566 };
1567 wkb.write_ewkb(w)?;
1568 }
1569 }
1570 }
1571 Ok(())
1572 }
1573}
1574
1575impl<'a, P> AsEwkbGeometryCollection<'a> for GeometryCollectionT<P>
1576where
1577 P: 'a + postgis::Point + EwkbRead,
1578{
1579 type PointType = P;
1580 type PointIter = Iter<'a, P>;
1581 type MultiPointType = MultiPointT<P>;
1582 type LineType = LineStringT<P>;
1583 type LineIter = Iter<'a, Self::LineType>;
1584 type MultiLineType = MultiLineStringT<P>;
1585 type PolyType = PolygonT<P>;
1586 type PolyIter = Iter<'a, Self::PolyType>;
1587 type MultiPolyType = MultiPolygonT<P>;
1588 type GeomType = GeometryT<P>;
1589 type GeomIter = Iter<'a, Self::GeomType>;
1590 type GeomCollection = GeometryCollectionT<P>;
1591 fn as_ewkb(
1592 &'a self,
1593 ) -> EwkbGeometryCollection<
1594 'a,
1595 Self::PointType,
1596 Self::PointIter,
1597 Self::MultiPointType,
1598 Self::LineType,
1599 Self::LineIter,
1600 Self::MultiLineType,
1601 Self::PolyType,
1602 Self::PolyIter,
1603 Self::MultiPolyType,
1604 Self::GeomType,
1605 Self::GeomIter,
1606 Self::GeomCollection,
1607 > {
1608 EwkbGeometryCollection {
1609 geom: self,
1610 srid: self.srid,
1611 point_type: P::point_type(),
1612 }
1613 }
1614}
1615
1616pub type GeometryCollection = GeometryCollectionT<Point>;
1618pub type GeometryCollectionZ = GeometryCollectionT<PointZ>;
1620pub type GeometryCollectionM = GeometryCollectionT<PointM>;
1622pub type GeometryCollectionZM = GeometryCollectionT<PointZM>;
1624
1625#[test]
1626#[cfg_attr(rustfmt, rustfmt_skip)]
1627fn test_point_write() {
1628 let point = Point { x: 10.0, y: -20.0, srid: None };
1630 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000000000000000000244000000000000034C0");
1631
1632 let point = PointZ { x: 10.0, y: -20.0, z: 100.0, srid: None };
1634 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000080000000000000244000000000000034C00000000000005940");
1635
1636 let point = PointM { x: 10.0, y: -20.0, m: 1.0, srid: None };
1638 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000040000000000000244000000000000034C0000000000000F03F");
1639
1640 let point = PointZM { x: 10.0, y: -20.0, z: 100.0, m: 1.0, srid: None };
1642 assert_eq!(point.as_ewkb().to_hex_ewkb(), "01010000C0000000000000244000000000000034C00000000000005940000000000000F03F");
1643
1644 let point = Point { x: 0.0, y: -1.0, srid: None };
1646 assert_eq!(point.as_ewkb().to_hex_ewkb(), "01010000000000000000000000000000000000F0BF");
1647 let point = Point { x: 10.0, y: -20.0, srid: Some(4326) };
1651 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000020E6100000000000000000244000000000000034C0");
1652}
1653
1654#[test]
1655#[cfg_attr(rustfmt, rustfmt_skip)]
1656fn test_line_write() {
1657 let p = |x, y| Point { x: x, y: y, srid: None };
1658 let line = LineStringT::<Point> {srid: None, points: vec![p(10.0, -20.0), p(0., -0.5)]};
1660 assert_eq!(line.as_ewkb().to_hex_ewkb(), "010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF");
1661
1662 let line = LineStringT::<Point> {srid: Some(4326), points: vec![p(10.0, -20.0), p(0., -0.5)]};
1664 assert_eq!(line.as_ewkb().to_hex_ewkb(), "0102000020E610000002000000000000000000244000000000000034C00000000000000000000000000000E0BF");
1665
1666 let p = |x, y, z| PointZ { x: x, y: y, z: z, srid: Some(4326) };
1667 let line = LineStringT::<PointZ> {srid: Some(4326), points: vec![p(10.0, -20.0, 100.0), p(0., -0.5, 101.0)]};
1669 assert_eq!(line.as_ewkb().to_hex_ewkb(), "01020000A0E610000002000000000000000000244000000000000034C000000000000059400000000000000000000000000000E0BF0000000000405940");
1670}
1671
1672#[test]
1673#[cfg_attr(rustfmt, rustfmt_skip)]
1674fn test_polygon_write() {
1675 let p = |x, y| Point { x: x, y: y, srid: Some(4326) };
1676 let line = LineStringT::<Point> {srid: Some(4326), points: vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]};
1678 let poly = PolygonT::<Point> {srid: Some(4326), rings: vec![line]};
1679 assert_eq!(poly.as_ewkb().to_hex_ewkb(), "0103000020E610000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000");
1680}
1681
1682#[test]
1683#[cfg_attr(rustfmt, rustfmt_skip)]
1684fn test_multipoint_write() {
1685 let p = |x, y, z| PointZ { x: x, y: y, z: z, srid: Some(4326) };
1686 let points = MultiPointT::<PointZ> {srid: Some(4326), points: vec![p(10.0, -20.0, 100.0), p(0., -0.5, 101.0)]};
1688 assert_eq!(points.as_ewkb().to_hex_ewkb(), "01040000A0E6100000020000000101000080000000000000244000000000000034C0000000000000594001010000800000000000000000000000000000E0BF0000000000405940");
1689}
1690
1691#[test]
1692#[cfg_attr(rustfmt, rustfmt_skip)]
1693fn test_multiline_write() {
1694 let p = |x, y| Point { x: x, y: y, srid: Some(4326) };
1695 let line1 = LineStringT::<Point> {srid: Some(4326), points: vec![p(10.0, -20.0), p(0., -0.5)]};
1697 let line2 = LineStringT::<Point> {srid: Some(4326), points: vec![p(0., 0.), p(2., 0.)]};
1698 let multiline = MultiLineStringT::<Point> {srid: Some(4326),lines: vec![line1, line2]};
1699 assert_eq!(multiline.as_ewkb().to_hex_ewkb(), "0105000020E610000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000");
1700}
1701
1702#[test]
1703#[cfg_attr(rustfmt, rustfmt_skip)]
1704fn test_multipolygon_write() {
1705 let p = |x, y| Point { x: x, y: y, srid: Some(4326) };
1706 let line = LineStringT::<Point> {srid: Some(4326), points: vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]};
1708 let poly1 = PolygonT::<Point> {srid: Some(4326), rings: vec![line]};
1709 let line = LineStringT::<Point> {srid: Some(4326), points: vec![p(10., 10.), p(-2., 10.), p(-2., -2.), p(10., -2.), p(10., 10.)]};
1710 let poly2 = PolygonT::<Point> {srid: Some(4326), rings: vec![line]};
1711 let multipoly = MultiPolygonT::<Point> {srid: Some(4326), polygons: vec![poly1, poly2]};
1712 assert_eq!(multipoly.as_ewkb().to_hex_ewkb(), "0106000020E610000002000000010300000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000010300000001000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
1713}
1714
1715#[test]
1716#[cfg_attr(rustfmt, rustfmt_skip)]
1717fn test_ewkb_adapters() {
1718 let point = Point { x: 10.0, y: -20.0, srid: Some(4326) };
1719 let ewkb = EwkbPoint { geom: &point, srid: Some(4326), point_type: PointType::Point };
1720 assert_eq!(ewkb.to_hex_ewkb(), "0101000020E6100000000000000000244000000000000034C0");
1721 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000020E6100000000000000000244000000000000034C0");
1722}
1723
1724#[cfg(test)]
1725#[cfg_attr(rustfmt, rustfmt_skip)]
1726fn hex_to_vec(hexstr: &str) -> Vec<u8> {
1727 hexstr.as_bytes().chunks(2).map(|chars| {
1728 let hb = if chars[0] <= 57 { chars[0] - 48 } else { chars[0] - 55 };
1729 let lb = if chars[1] <= 57 { chars[1] - 48 } else { chars[1] - 55 };
1730 hb * 16 + lb
1731 }).collect::<Vec<_>>()
1732}
1733
1734#[test]
1735#[cfg_attr(rustfmt, rustfmt_skip)]
1736fn test_point_read() {
1737 let ewkb = hex_to_vec("0101000000000000000000244000000000000034C0");
1739 assert_eq!(ewkb, &[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 0, 0, 0, 0, 0, 52, 192]);
1740 let point = Point::read_ewkb(&mut ewkb.as_slice()).unwrap();
1741 assert_eq!(point, Point { x: 10.0, y: -20.0, srid: None });
1742
1743 let ewkb = hex_to_vec("0101000080000000000000244000000000000034C00000000000005940");
1745 let point = PointZ::read_ewkb(&mut ewkb.as_slice()).unwrap();
1746 assert_eq!(point, PointZ { x: 10.0, y: -20.0, z: 100.0, srid: None });
1747
1748 let point = Point::read_ewkb(&mut ewkb.as_slice()).unwrap();
1749 assert_eq!(point, Point { x: 10.0, y: -20.0, srid: None });
1750
1751 let ewkb = hex_to_vec("0101000040000000000000244000000000000034C0000000000000F03F");
1753 let point = PointM::read_ewkb(&mut ewkb.as_slice()).unwrap();
1754 assert_eq!(point, PointM { x: 10.0, y: -20.0, m: 1.0, srid: None });
1755
1756 let ewkb = hex_to_vec("01010000C0000000000000244000000000000034C00000000000005940000000000000F03F");
1758 let point = PointZM::read_ewkb(&mut ewkb.as_slice()).unwrap();
1759 assert_eq!(point, PointZM { x: 10.0, y: -20.0, z: 100.0, m: 1.0, srid: None });
1760}
1761
1762#[test]
1763#[cfg_attr(rustfmt, rustfmt_skip)]
1764fn test_line_read() {
1765 let p = |x, y| Point { x: x, y: y, srid: None };
1766 let ewkb = hex_to_vec("010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF");
1768 let line = LineStringT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1769 assert_eq!(line, LineStringT::<Point> {srid: None, points: vec![p(10.0, -20.0), p(0., -0.5)]});
1770
1771 let p = |x, y, z| PointZ { x: x, y: y, z: z, srid: Some(4326) };
1772 let ewkb = hex_to_vec("01020000A0E610000002000000000000000000244000000000000034C000000000000059400000000000000000000000000000E0BF0000000000405940");
1774 let line = LineStringT::<PointZ>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1775 assert_eq!(line, LineStringT::<PointZ> {srid: Some(4326), points: vec![p(10.0, -20.0, 100.0), p(0., -0.5, 101.0)]});
1776}
1777
1778#[test]
1779#[cfg_attr(rustfmt, rustfmt_skip)]
1780fn test_polygon_read() {
1781 let p = |x, y| Point { x: x, y: y, srid: Some(4326) };
1782 let ewkb = hex_to_vec("0103000020E610000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000");
1784 let poly = PolygonT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1785 let line = LineStringT::<Point> {srid: Some(4326), points: vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]};
1786 assert_eq!(poly, PolygonT::<Point> {srid: Some(4326), rings: vec![line]});
1787}
1788
1789#[test]
1790#[cfg_attr(rustfmt, rustfmt_skip)]
1791fn test_multipoint_read() {
1792 let p = |x, y, z| PointZ { x: x, y: y, z: z, srid: None }; let ewkb = hex_to_vec("01040000A0E6100000020000000101000080000000000000244000000000000034C0000000000000594001010000800000000000000000000000000000E0BF0000000000405940");
1795 let points = MultiPointT::<PointZ>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1796 assert_eq!(points, MultiPointT::<PointZ> {srid: Some(4326), points: vec![p(10.0, -20.0, 100.0), p(0., -0.5, 101.0)]});
1797}
1798
1799#[test]
1800#[cfg_attr(rustfmt, rustfmt_skip)]
1801fn test_multiline_read() {
1802 let p = |x, y| Point { x: x, y: y, srid: None }; let ewkb = hex_to_vec("0105000020E610000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000");
1805 let poly = MultiLineStringT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1806 let line1 = LineStringT::<Point> {srid: None, points: vec![p(10.0, -20.0), p(0., -0.5)]};
1807 let line2 = LineStringT::<Point> {srid: None, points: vec![p(0., 0.), p(2., 0.)]};
1808 assert_eq!(poly, MultiLineStringT::<Point> {srid: Some(4326), lines: vec![line1, line2]});
1809}
1810
1811#[test]
1812#[cfg_attr(rustfmt, rustfmt_skip)]
1813fn test_multipolygon_read() {
1814 let p = |x, y| Point { x: x, y: y, srid: None }; let ewkb = hex_to_vec("0106000020E610000002000000010300000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000010300000001000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
1817 let multipoly = MultiPolygonT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1818 let line = LineStringT::<Point> {srid: None, points: vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]};
1819 let poly1 = PolygonT::<Point> {srid: None, rings: vec![line]};
1820 let line = LineStringT::<Point> {srid: None, points: vec![p(10., 10.), p(-2., 10.), p(-2., -2.), p(10., -2.), p(10., 10.)]};
1821 let poly2 = PolygonT::<Point> {srid: None, rings: vec![line]};
1822 assert_eq!(multipoly, MultiPolygonT::<Point> {srid: Some(4326), polygons: vec![poly1, poly2]});
1823}
1824
1825#[test]
1826#[cfg_attr(rustfmt, rustfmt_skip)]
1827fn test_geometrycollection_read() {
1828 let ewkb = hex_to_vec("01070000000300000001010000000000000000002440000000000000244001010000000000000000003E400000000000003E400102000000020000000000000000002E400000000000002E4000000000000034400000000000003440");
1830 let geom = GeometryCollectionT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1831 assert_eq!(format!("{:.0?}", geom), "GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })], srid: None }");
1832}
1833
1834#[test]
1835#[cfg_attr(rustfmt, rustfmt_skip)]
1836fn test_geometry_read() {
1837 let ewkb = hex_to_vec("01010000C0000000000000244000000000000034C00000000000005940000000000000F03F");
1839 let geom = GeometryT::<PointZM>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1840 assert_eq!(format!("{:.0?}", geom), "Point(PointZM { x: 10, y: -20, z: 100, m: 1, srid: None })");
1841 let ewkb = hex_to_vec("01020000A0E610000002000000000000000000244000000000000034C000000000000059400000000000000000000000000000E0BF0000000000405940");
1843 let geom = GeometryT::<PointZ>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1844 assert_eq!(format!("{:.1?}", geom), "LineString(LineStringT { points: [PointZ { x: 10.0, y: -20.0, z: 100.0, srid: Some(4326) }, PointZ { x: 0.0, y: -0.5, z: 101.0, srid: Some(4326) }], srid: Some(4326) })");
1845 let ewkb = hex_to_vec("0103000020E610000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000");
1847 let geom = GeometryT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1848 assert_eq!(format!("{:.0?}", geom), "Polygon(PolygonT { rings: [LineStringT { points: [Point { x: 0, y: 0, srid: Some(4326) }, Point { x: 2, y: 0, srid: Some(4326) }, Point { x: 2, y: 2, srid: Some(4326) }, Point { x: 0, y: 2, srid: Some(4326) }, Point { x: 0, y: 0, srid: Some(4326) }], srid: Some(4326) }], srid: Some(4326) })");
1849 let ewkb = hex_to_vec("01040000A0E6100000020000000101000080000000000000244000000000000034C0000000000000594001010000800000000000000000000000000000E0BF0000000000405940");
1851 let geom = GeometryT::<PointZ>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1852 assert_eq!(format!("{:.1?}", geom), "MultiPoint(MultiPointT { points: [PointZ { x: 10.0, y: -20.0, z: 100.0, srid: None }, PointZ { x: 0.0, y: -0.5, z: 101.0, srid: None }], srid: Some(4326) })");
1853 let ewkb = hex_to_vec("0105000020E610000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000");
1855 let geom = GeometryT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1856 assert_eq!(format!("{:.1?}", geom), "MultiLineString(MultiLineStringT { lines: [LineStringT { points: [Point { x: 10.0, y: -20.0, srid: None }, Point { x: 0.0, y: -0.5, srid: None }], srid: None }, LineStringT { points: [Point { x: 0.0, y: 0.0, srid: None }, Point { x: 2.0, y: 0.0, srid: None }], srid: None }], srid: Some(4326) })");
1857 let ewkb = hex_to_vec("0106000020E610000002000000010300000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000010300000001000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
1859 let geom = GeometryT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1860 assert_eq!(format!("{:.0?}", geom), "MultiPolygon(MultiPolygonT { polygons: [PolygonT { rings: [LineStringT { points: [Point { x: 0, y: 0, srid: None }, Point { x: 2, y: 0, srid: None }, Point { x: 2, y: 2, srid: None }, Point { x: 0, y: 2, srid: None }, Point { x: 0, y: 0, srid: None }], srid: None }], srid: None }, PolygonT { rings: [LineStringT { points: [Point { x: 10, y: 10, srid: None }, Point { x: -2, y: 10, srid: None }, Point { x: -2, y: -2, srid: None }, Point { x: 10, y: -2, srid: None }, Point { x: 10, y: 10, srid: None }], srid: None }], srid: None }], srid: Some(4326) })");
1861 let ewkb = hex_to_vec("01070000000300000001010000000000000000002440000000000000244001010000000000000000003E400000000000003E400102000000020000000000000000002E400000000000002E4000000000000034400000000000003440");
1863 let geom = GeometryT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1864 assert_eq!(format!("{:.0?}", geom), "GeometryCollection(GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })], srid: None })");
1865}
1866
1867#[test]
1868#[cfg_attr(rustfmt, rustfmt_skip)]
1869fn test_read_error() {
1870 let ewkb = hex_to_vec("010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF");
1872 let poly = PolygonT::<Point>::read_ewkb(&mut ewkb.as_slice());
1873 assert!(poly.is_err()); }
1875
1876#[test]
1877#[cfg_attr(rustfmt, rustfmt_skip)]
1878fn test_iterators() {
1879 use crate::types::LineString;
1881
1882 let p = |x, y| Point { x: x, y: y, srid: None };
1883 let line = self::LineStringT::<Point> {srid: Some(4326), points: vec![p(10.0, -20.0), p(0., -0.5)]};
1884 assert_eq!(line.points().last(), Some(&Point { x: 0., y: -0.5, srid: None }));
1885}