postgis_diesel/
multipoint.rs

1use crate::write_to_read_from_sql::{ReadFromSql, WriteToSql};
2use crate::{
3    ewkb::{EwkbSerializable, GeometryType},
4    points::Dimension,
5    types::*,
6};
7use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
8
9impl<P> MultiPoint<P>
10where
11    P: PointT,
12{
13    pub fn new(srid: Option<u32>) -> Self {
14        Self::with_capacity(srid, 0)
15    }
16
17    pub fn with_capacity(srid: Option<u32>, cap: usize) -> Self {
18        MultiPoint {
19            points: Vec::with_capacity(cap),
20            srid,
21        }
22    }
23
24    pub fn add_point(&mut self, point: P) -> &mut Self {
25        self.points.push(point);
26        self
27    }
28
29    pub fn add_points(&mut self, points: impl IntoIterator<Item = P>) -> &mut Self {
30        for point in points {
31            self.points.push(point);
32        }
33        self
34    }
35
36    pub fn dimension(&self) -> u32 {
37        let mut dimension = Dimension::NONE;
38        if let Some(point) = self.points.first() {
39            dimension |= point.dimension();
40        }
41        dimension
42    }
43}
44
45impl<P> EwkbSerializable for MultiPoint<P>
46where
47    P: PointT,
48{
49    fn expected_geometry_variant(_: u32) -> GeometryType {
50        GeometryType::MultiPoint
51    }
52
53    fn geometry_type(&self) -> u32 {
54        let mut g_type = GeometryType::MultiPoint as u32;
55        if let Some(point) = self.points.first() {
56            g_type |= point.dimension();
57        }
58        g_type
59    }
60
61    fn srid(&self) -> Option<u32> {
62        self.srid
63    }
64}
65
66impl<P> ReadFromSql for MultiPoint<P>
67where
68    P: PointT,
69{
70    fn read_body<Endianness, Reader>(
71        header: crate::ewkb::EwkbHeader,
72        reader: &mut Reader,
73    ) -> Result<Self, std::io::Error>
74    where
75        Reader: std::io::Read,
76        Endianness: byteorder::ByteOrder,
77    {
78        let len = reader.read_u32::<Endianness>()?;
79        let mut mp = MultiPoint::with_capacity(header.srid, len as usize);
80        for _i in 0..len {
81            // skip 1 byte for byte order and 4 bytes for point type
82            reader.read_u8()?;
83            reader.read_u32::<Endianness>()?;
84            mp.add_point(P::read_body::<Endianness, Reader>(header, reader)?);
85        }
86        Ok(mp)
87    }
88}
89
90impl<P> WriteToSql for MultiPoint<P>
91where
92    P: PointT,
93{
94    fn write_body<Writer>(&self, out: &mut Writer) -> Result<(), std::io::Error>
95    where
96        Writer: std::io::Write,
97    {
98        out.write_u32::<LittleEndian>(self.points.len() as u32)?;
99        for point in self.points.iter() {
100            point.write_to_sql::<Writer>(false, out)?;
101        }
102        Ok(())
103    }
104}