Skip to content

Commit e07b7b0

Browse files
committed
Support PATH type with geo::LineString
1 parent efbf30c commit e07b7b0

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,13 @@ types. The driver currently supports the following conversions:
268268
</td>
269269
<td>BOX</td>
270270
</tr>
271+
<tr>
272+
<td>
273+
<a href="https://github.com/georust/rust-geo">geo::LineString&lt;f64&gt;</a>
274+
(<a href="#optional-features">optional</a>)
275+
</td>
276+
<td>PATH</td>
277+
</tr>
271278
</tbody>
272279
</table>
273280

@@ -340,3 +347,11 @@ support is provided optionally by the `with-geo` feature, which adds `ToSql` and
340347

341348
[BOX](https://www.postgresql.org/docs/9.4/static/datatype-geometric.html#AEN6883)
342349
support is provided optionally by the `with-geo` feature, which adds `ToSql` and `FromSql` implementations for `geo`'s `Bbox` type.
350+
351+
### PATH type
352+
353+
[PATH](https://www.postgresql.org/docs/9.4/static/datatype-geometric.html#AEN6912)
354+
support is provided optionally by the `with-geo` feature, which adds `ToSql` and `FromSql` implementations for `geo`'s `LineString` type.
355+
Paths converted from LineString are always treated as "open" paths. Use the
356+
[pclose](https://www.postgresql.org/docs/8.2/static/functions-geometry.html#FUNCTIONS-GEOMETRY-FUNC-TABLE)
357+
geometric function to insert a closed path.

postgres-shared/src/types/geo.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate geo;
22

33
use postgres_protocol::types;
4-
use self::geo::{Bbox, Point};
4+
use self::geo::{Bbox, LineString, Point};
55
use std::error::Error;
66

77
use types::{FromSql, ToSql, IsNull, Type};
@@ -59,3 +59,44 @@ impl ToSql for Bbox<f64> {
5959
accepts!(Type::Box);
6060
to_sql_checked!();
6161
}
62+
63+
impl FromSql for LineString<f64> {
64+
fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<Error + Sync + Send>> {
65+
if raw.len() < 5 {
66+
return Err("invalid message length".into());
67+
}
68+
69+
// let _ = types::bool_from_sql(&raw[0..1])?; // is path open or closed
70+
let n_points = types::int4_from_sql(&raw[1..5])? as usize;
71+
let raw_points = &raw[5..raw.len()-1];
72+
if raw_points.len() != 16 * n_points {
73+
return Err("invalid message length".into());
74+
}
75+
76+
let mut points = Vec::with_capacity(n_points);
77+
for n in 0..n_points {
78+
let x = types::float8_from_sql(&raw[n..n+8])?;
79+
let y = types::float8_from_sql(&raw[n+8..n+16])?;
80+
points.push(Point::new(x, y));
81+
}
82+
Ok(LineString(points))
83+
}
84+
85+
accepts!(Type::Path);
86+
}
87+
88+
impl ToSql for LineString<f64> {
89+
fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
90+
let closed = false; // always encode an open path from LineString
91+
types::bool_to_sql(closed, out);
92+
types::int4_to_sql(self.0.len() as i32, out);
93+
for point in &self.0 {
94+
types::float8_to_sql(point.x(), out);
95+
types::float8_to_sql(point.y(), out);
96+
}
97+
Ok(IsNull::No)
98+
}
99+
100+
accepts!(Type::Path);
101+
to_sql_checked!();
102+
}

0 commit comments

Comments
 (0)