postgis_diesel/
geometrycontainer.rs

1use std::fmt::Debug;
2use std::io::Cursor;
3
4use crate::{
5    ewkb::{EwkbSerializable, GeometryType, BIG_ENDIAN},
6    polygon::*,
7    sql_types::{Geography, Geometry},
8    types::*,
9};
10
11#[cfg(feature = "diesel")]
12use crate::{
13    ewkb::read_ewkb_header,
14    geometrycollection::{read_geometry_collection_body, write_geometry_collection},
15    linestring::{read_linestring_body, write_linestring},
16    multiline::{read_multiline_body, write_multiline},
17    multipoint::{read_multi_point_body, write_multi_point},
18    multipolygon::{read_multi_polygon_body, write_multi_polygon},
19    points::{read_point_coordinates, write_point},
20};
21
22use byteorder::{BigEndian, LittleEndian};
23
24impl<T> GeometryContainer<T>
25where
26    T: PointT + Clone,
27{
28    pub fn dimension(&self) -> u32 {
29        match self {
30            GeometryContainer::Point(g) => g.dimension(),
31            GeometryContainer::LineString(g) => g.dimension(),
32            GeometryContainer::Polygon(g) => g.dimension(),
33            GeometryContainer::MultiPoint(g) => g.dimension(),
34            GeometryContainer::MultiLineString(g) => g.dimension(),
35            GeometryContainer::MultiPolygon(g) => g.dimension(),
36            GeometryContainer::GeometryCollection(g) => g.dimension(),
37        }
38    }
39}
40
41#[cfg(feature = "diesel")]
42impl<T> diesel::serialize::ToSql<Geometry, diesel::pg::Pg> for GeometryContainer<T>
43where
44    T: PointT
45        + Debug
46        + PartialEq
47        + Clone
48        + EwkbSerializable
49        + diesel::serialize::ToSql<Geometry, diesel::pg::Pg>,
50{
51    fn to_sql(
52        &self,
53        out: &mut diesel::serialize::Output<diesel::pg::Pg>,
54    ) -> diesel::serialize::Result {
55        match self {
56            GeometryContainer::Point(g) => write_point(g, g.get_srid(), out),
57            GeometryContainer::MultiPoint(g) => write_multi_point(g, g.srid, out),
58            GeometryContainer::LineString(g) => write_linestring(g, g.srid, out),
59            GeometryContainer::MultiLineString(g) => write_multiline(g, g.srid, out),
60            GeometryContainer::Polygon(g) => write_polygon(g, g.srid, out),
61            GeometryContainer::MultiPolygon(g) => write_multi_polygon(g, g.srid, out),
62            GeometryContainer::GeometryCollection(g) => write_geometry_collection(g, g.srid, out),
63        }
64    }
65}
66
67#[cfg(feature = "diesel")]
68impl<T> diesel::serialize::ToSql<Geography, diesel::pg::Pg> for GeometryContainer<T>
69where
70    T: PointT
71        + Debug
72        + PartialEq
73        + Clone
74        + EwkbSerializable
75        + diesel::serialize::ToSql<Geometry, diesel::pg::Pg>,
76{
77    fn to_sql(
78        &self,
79        out: &mut diesel::serialize::Output<diesel::pg::Pg>,
80    ) -> diesel::serialize::Result {
81        match self {
82            GeometryContainer::Point(g) => write_point(g, g.get_srid(), out),
83            GeometryContainer::MultiPoint(g) => write_multi_point(g, g.srid, out),
84            GeometryContainer::LineString(g) => write_linestring(g, g.srid, out),
85            GeometryContainer::MultiLineString(g) => write_multiline(g, g.srid, out),
86            GeometryContainer::Polygon(g) => write_polygon(g, g.srid, out),
87            GeometryContainer::MultiPolygon(g) => write_multi_polygon(g, g.srid, out),
88            GeometryContainer::GeometryCollection(g) => write_geometry_collection(g, g.srid, out),
89        }
90    }
91}
92
93#[cfg(feature = "diesel")]
94impl<T> diesel::deserialize::FromSql<Geometry, diesel::pg::Pg> for GeometryContainer<T>
95where
96    T: PointT + Debug + Clone + diesel::deserialize::FromSql<Geometry, diesel::pg::Pg>,
97{
98    fn from_sql(bytes: diesel::pg::PgValue) -> diesel::deserialize::Result<Self> {
99        use byteorder::ReadBytesExt;
100
101        let mut cursor = Cursor::new(bytes.as_bytes());
102        let end = cursor.read_u8()?;
103        let container = if end == BIG_ENDIAN {
104            let g_header = read_ewkb_header::<BigEndian>(&mut cursor)?;
105            match GeometryType::from(g_header.g_type) {
106                GeometryType::Point => {
107                    GeometryContainer::Point(read_point_coordinates::<BigEndian, T>(
108                        &mut cursor,
109                        g_header.g_type,
110                        g_header.srid,
111                    )?)
112                }
113                GeometryType::MultiPoint => {
114                    GeometryContainer::MultiPoint(read_multi_point_body::<BigEndian, T>(
115                        g_header.g_type,
116                        g_header.srid,
117                        &mut cursor,
118                    )?)
119                }
120                GeometryType::LineString => {
121                    GeometryContainer::LineString(read_linestring_body::<BigEndian, T>(
122                        g_header.g_type,
123                        g_header.srid,
124                        &mut cursor,
125                    )?)
126                }
127                GeometryType::MultiLineString => {
128                    GeometryContainer::MultiLineString(read_multiline_body::<BigEndian, T>(
129                        g_header.g_type,
130                        g_header.srid,
131                        &mut cursor,
132                    )?)
133                }
134                GeometryType::Polygon => {
135                    GeometryContainer::Polygon(read_polygon_body::<BigEndian, T>(
136                        g_header.g_type,
137                        g_header.srid,
138                        &mut cursor,
139                    )?)
140                }
141                GeometryType::MultiPolygon => {
142                    GeometryContainer::MultiPolygon(read_multi_polygon_body::<BigEndian, T>(
143                        g_header.g_type,
144                        g_header.srid,
145                        &mut cursor,
146                    )?)
147                }
148                GeometryType::GeometryCollection => {
149                    GeometryContainer::GeometryCollection(read_geometry_collection_body::<
150                        BigEndian,
151                        T,
152                    >(
153                        g_header.g_type,
154                        g_header.srid,
155                        &mut cursor,
156                    )?)
157                }
158            }
159        } else {
160            let g_header = read_ewkb_header::<LittleEndian>(&mut cursor)?;
161            match GeometryType::from(g_header.g_type) {
162                GeometryType::Point => {
163                    GeometryContainer::Point(read_point_coordinates::<LittleEndian, T>(
164                        &mut cursor,
165                        g_header.g_type,
166                        g_header.srid,
167                    )?)
168                }
169                GeometryType::MultiPoint => {
170                    GeometryContainer::MultiPoint(read_multi_point_body::<LittleEndian, T>(
171                        g_header.g_type,
172                        g_header.srid,
173                        &mut cursor,
174                    )?)
175                }
176                GeometryType::LineString => {
177                    GeometryContainer::LineString(read_linestring_body::<LittleEndian, T>(
178                        g_header.g_type,
179                        g_header.srid,
180                        &mut cursor,
181                    )?)
182                }
183                GeometryType::MultiLineString => {
184                    GeometryContainer::MultiLineString(read_multiline_body::<LittleEndian, T>(
185                        g_header.g_type,
186                        g_header.srid,
187                        &mut cursor,
188                    )?)
189                }
190                GeometryType::Polygon => {
191                    GeometryContainer::Polygon(read_polygon_body::<LittleEndian, T>(
192                        g_header.g_type,
193                        g_header.srid,
194                        &mut cursor,
195                    )?)
196                }
197                GeometryType::MultiPolygon => {
198                    GeometryContainer::MultiPolygon(read_multi_polygon_body::<LittleEndian, T>(
199                        g_header.g_type,
200                        g_header.srid,
201                        &mut cursor,
202                    )?)
203                }
204                GeometryType::GeometryCollection => {
205                    GeometryContainer::GeometryCollection(read_geometry_collection_body::<
206                        LittleEndian,
207                        T,
208                    >(
209                        g_header.g_type,
210                        g_header.srid,
211                        &mut cursor,
212                    )?)
213                }
214            }
215        };
216        Ok(container)
217    }
218}
219
220#[cfg(feature = "diesel")]
221impl<T> diesel::deserialize::FromSql<Geography, diesel::pg::Pg> for GeometryContainer<T>
222where
223    T: PointT + Debug + Clone + diesel::deserialize::FromSql<Geometry, diesel::pg::Pg>,
224{
225    fn from_sql(bytes: diesel::pg::PgValue) -> diesel::deserialize::Result<Self> {
226        diesel::deserialize::FromSql::<Geometry, diesel::pg::Pg>::from_sql(bytes)
227    }
228}