postgis_butmaintained/ewkb/container/
point.rs1use crate::ewkb::encoding::*;
2use crate::ewkb::point::*;
3use crate::ewkb::{EwkbPoint, EwkbRead, EwkbWrite};
4use crate::{error::Error, types as postgis};
5use byteorder::LittleEndian;
6use byteorder::WriteBytesExt;
7use std::fmt;
8use std::io::{Read, Write};
9use std::iter::FromIterator;
10use std::slice::Iter;
11
12macro_rules! point_container_type {
13 ($geotypetrait:ident for $geotype:ident) => {
15 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17 #[derive(PartialEq, Clone, Debug)]
18 pub struct $geotype<P: postgis::Point + EwkbRead> {
19 pub points: Vec<P>,
20 pub srid: Option<i32>,
21 }
22
23 impl<P: postgis::Point + EwkbRead> Default for $geotype<P> {
24 fn default() -> Self {
25 Self::new()
26 }
27 }
28
29 impl<P: postgis::Point + EwkbRead> $geotype<P> {
30 pub fn new() -> $geotype<P> {
31 $geotype {
32 points: Vec::new(),
33 srid: None,
34 }
35 }
36 }
37
38 impl<P> FromIterator<P> for $geotype<P>
39 where
40 P: postgis::Point + EwkbRead,
41 {
42 #[inline]
43 fn from_iter<I: IntoIterator<Item = P>>(iterable: I) -> $geotype<P> {
44 let iterator = iterable.into_iter();
45 let (lower, _) = iterator.size_hint();
46 let mut ret = $geotype::new();
47 ret.points.reserve(lower);
48 for item in iterator {
49 ret.points.push(item);
50 }
51 ret
52 }
53 }
54
55 impl<'a, P> postgis::$geotypetrait<'a> for $geotype<P>
56 where
57 P: 'a + postgis::Point + EwkbRead,
58 {
59 type ItemType = P;
60 type Iter = Iter<'a, Self::ItemType>;
61 fn points(&'a self) -> Self::Iter {
62 self.points.iter()
63 }
64 }
65 };
66}
67
68macro_rules! impl_read_for_point_container_type {
69 (singletype $geotype:ident) => {
70 impl<P> EwkbRead for $geotype<P>
71 where
72 P: postgis::Point + EwkbRead,
73 {
74 fn point_type() -> PointType {
75 P::point_type()
76 }
77 fn read_ewkb_body<R: Read>(
78 raw: &mut R,
79 is_be: bool,
80 type_id: u32,
81 srid: Option<i32>,
82 ) -> Result<Self, Error> {
83 let mut points: Vec<P> = vec![];
84 let size = read_u32(raw, is_be)? as usize;
85 for _ in 0..size {
86 points.push(P::read_ewkb_body(raw, is_be, type_id, srid)?);
87 }
88 Ok($geotype::<P> {
89 points,
90 srid,
91 })
92 }
93 }
94 };
95 (multitype $geotype:ident) => {
96 impl<P> EwkbRead for $geotype<P>
97 where
98 P: postgis::Point + EwkbRead,
99 {
100 fn point_type() -> PointType {
101 P::point_type()
102 }
103 fn read_ewkb_body<R: Read>(
104 raw: &mut R,
105 is_be: bool,
106 _type_id: u32,
107 srid: Option<i32>,
108 ) -> Result<Self, Error> {
109 let mut points: Vec<P> = vec![];
110 let size = read_u32(raw, is_be)? as usize;
111 for _ in 0..size {
112 points.push(P::read_ewkb(raw)?);
113 }
114 Ok($geotype::<P> {
115 points,
116 srid,
117 })
118 }
119 }
120 };
121}
122
123macro_rules! point_container_write {
124 ($geotypetrait:ident and $asewkbtype:ident for $geotype:ident to $ewkbtype:ident with type code $typecode:expr, command $writecmd:ident) => {
125 pub struct $ewkbtype<'a, P, I>
126 where
127 P: 'a + postgis::Point,
128 I: 'a + Iterator<Item = &'a P> + ExactSizeIterator<Item = &'a P>,
129 {
130 pub geom: &'a dyn postgis::$geotypetrait<'a, ItemType = P, Iter = I>,
131 pub srid: Option<i32>,
132 pub point_type: PointType,
133 }
134
135 pub trait $asewkbtype<'a> {
136 type PointType: 'a + postgis::Point;
137 type Iter: Iterator<Item = &'a Self::PointType>
138 + ExactSizeIterator<Item = &'a Self::PointType>;
139 fn as_ewkb(&'a self) -> $ewkbtype<'a, Self::PointType, Self::Iter>;
140 }
141
142 impl<'a, T, I> fmt::Debug for $ewkbtype<'a, T, I>
143 where
144 T: 'a + postgis::Point,
145 I: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
146 {
147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
148 write!(f, stringify!($ewkbtype))?; Ok(())
150 }
151 }
152
153 impl<'a, T, I> EwkbWrite for $ewkbtype<'a, T, I>
154 where
155 T: 'a + postgis::Point,
156 I: 'a + Iterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>,
157 {
158 fn opt_srid(&self) -> Option<i32> {
159 self.srid
160 }
161
162 fn type_id(&self) -> u32 {
163 $typecode | Self::wkb_type_id(&self.point_type, self.srid)
164 }
165
166 fn write_ewkb_body<W: Write + ?Sized>(&self, w: &mut W) -> Result<(), Error> {
167 w.write_u32::<LittleEndian>(self.geom.points().len() as u32)?;
168 for geom in self.geom.points() {
169 let wkb = EwkbPoint {
170 geom,
171 srid: None,
172 point_type: self.point_type.clone(),
173 };
174 wkb.$writecmd(w)?;
175 }
176 Ok(())
177 }
178 }
179
180 impl<'a, P> $asewkbtype<'a> for $geotype<P>
181 where
182 P: 'a + postgis::Point + EwkbRead,
183 {
184 type PointType = P;
185 type Iter = Iter<'a, P>;
186 fn as_ewkb(&'a self) -> $ewkbtype<'a, Self::PointType, Self::Iter> {
187 $ewkbtype {
188 geom: self,
189 srid: self.srid,
190 point_type: Self::PointType::point_type(),
191 }
192 }
193 }
194 };
195}
196
197point_container_type!(LineString for LineStringT);
198impl_read_for_point_container_type!(singletype LineStringT);
199point_container_write!(LineString and AsEwkbLineString for LineStringT
200 to EwkbLineString with type code 0x02,
201 command write_ewkb_body);
202
203pub type LineString = LineStringT<Point>;
205pub type LineStringZ = LineStringT<PointZ>;
207pub type LineStringM = LineStringT<PointM>;
209pub type LineStringZM = LineStringT<PointZM>;
211
212point_container_type!(MultiPoint for MultiPointT);
213impl_read_for_point_container_type!(multitype MultiPointT);
214point_container_write!(MultiPoint and AsEwkbMultiPoint for MultiPointT
215 to EwkbMultiPoint with type code 0x04,
216 command write_ewkb);
217
218pub type MultiPoint = MultiPointT<Point>;
220pub type MultiPointZ = MultiPointT<PointZ>;
222pub type MultiPointM = MultiPointT<PointM>;
224pub type MultiPointZM = MultiPointT<PointZM>;