diff --git a/README.md b/README.md
index 7fd938ba..804740ac 100644
--- a/README.md
+++ b/README.md
@@ -268,6 +268,13 @@ types. The driver currently supports the following conversions:
BOX |
+
+
+ geo::LineString<f64>
+ (optional)
+ |
+ PATH |
+
@@ -340,3 +347,11 @@ support is provided optionally by the `with-geo` feature, which adds `ToSql` and
[BOX](https://www.postgresql.org/docs/9.4/static/datatype-geometric.html#AEN6883)
support is provided optionally by the `with-geo` feature, which adds `ToSql` and `FromSql` implementations for `geo`'s `Bbox` type.
+
+### PATH type
+
+[PATH](https://www.postgresql.org/docs/9.4/static/datatype-geometric.html#AEN6912)
+support is provided optionally by the `with-geo` feature, which adds `ToSql` and `FromSql` implementations for `geo`'s `LineString` type.
+Paths converted from LineString are always treated as "open" paths. Use the
+[pclose](https://www.postgresql.org/docs/8.2/static/functions-geometry.html#FUNCTIONS-GEOMETRY-FUNC-TABLE)
+geometric function to insert a closed path.
diff --git a/postgres-shared/src/types/geo.rs b/postgres-shared/src/types/geo.rs
index 62e38f2a..e6bb2e11 100644
--- a/postgres-shared/src/types/geo.rs
+++ b/postgres-shared/src/types/geo.rs
@@ -1,7 +1,7 @@
extern crate geo;
use postgres_protocol::types;
-use self::geo::{Bbox, Point};
+use self::geo::{Bbox, LineString, Point};
use std::error::Error;
use types::{FromSql, ToSql, IsNull, Type};
@@ -59,3 +59,44 @@ impl ToSql for Bbox {
accepts!(Type::Box);
to_sql_checked!();
}
+
+impl FromSql for LineString {
+ fn from_sql(_: &Type, raw: &[u8]) -> Result> {
+ if raw.len() < 5 {
+ return Err("invalid message length".into());
+ }
+
+ // let _ = types::bool_from_sql(&raw[0..1])?; // is path open or closed
+ let n_points = types::int4_from_sql(&raw[1..5])? as usize;
+ let raw_points = &raw[5..raw.len()-1];
+ if raw_points.len() != 16 * n_points {
+ return Err("invalid message length".into());
+ }
+
+ let mut points = Vec::with_capacity(n_points);
+ for n in 0..n_points {
+ let x = types::float8_from_sql(&raw[n..n+8])?;
+ let y = types::float8_from_sql(&raw[n+8..n+16])?;
+ points.push(Point::new(x, y));
+ }
+ Ok(LineString(points))
+ }
+
+ accepts!(Type::Path);
+}
+
+impl ToSql for LineString {
+ fn to_sql(&self, _: &Type, out: &mut Vec) -> Result> {
+ let closed = false; // always encode an open path from LineString
+ types::bool_to_sql(closed, out);
+ types::int4_to_sql(self.0.len() as i32, out);
+ for point in &self.0 {
+ types::float8_to_sql(point.x(), out);
+ types::float8_to_sql(point.y(), out);
+ }
+ Ok(IsNull::No)
+ }
+
+ accepts!(Type::Path);
+ to_sql_checked!();
+}