Skip to content

Commit 7b69e14

Browse files
committed
Implement ToSql for GeometryCollection
1 parent abc984c commit 7b69e14

File tree

3 files changed

+44
-38
lines changed

3 files changed

+44
-38
lines changed

src/ewkb.rs

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -961,42 +961,34 @@ impl<'a, P, PI, MP, L, LI, ML, Y, YI, MY, G, GI, GC> EwkbWrite for EwkbGeometry<
961961
}
962962
}
963963

964-
// NOTE: Implement once for each point type to avoid trait lifetime constraints
965-
macro_rules! impl_as_ewkb_geometry {
966-
($ptype:ident) => (
967-
impl<'a> AsEwkbGeometry<'a> for GeometryT<$ptype> {
968-
type PointType = $ptype;
969-
type PointIter = Iter<'a, $ptype>;
970-
type MultiPointType = MultiPointT<$ptype>;
971-
type LineType = LineStringT<$ptype>;
972-
type LineIter = Iter<'a, Self::LineType>;
973-
type MultiLineType = MultiLineStringT<$ptype>;
974-
type PolyType = PolygonT<$ptype>;
975-
type PolyIter = Iter<'a, Self::PolyType>;
976-
type MultiPolyType = MultiPolygonT<$ptype>;
977-
type GeomType = GeometryT<$ptype>;
978-
type GeomIter = Iter<'a, Self::GeomType>;
979-
type GeomCollection = GeometryCollectionT<$ptype>;
980-
fn as_ewkb(&'a self) -> EwkbGeometry<'a, Self::PointType, Self::PointIter, Self::MultiPointType, Self::LineType, Self::LineIter, Self::MultiLineType, Self::PolyType, Self::PolyIter, Self::MultiPolyType, Self::GeomType, Self::GeomIter, Self::GeomCollection> {
981-
match *self {
982-
GeometryT::Point(ref geom) => EwkbGeometry::Point(geom.as_ewkb()),
983-
GeometryT::LineString(ref geom) => EwkbGeometry::LineString(geom.as_ewkb()),
984-
GeometryT::Polygon(ref geom) => EwkbGeometry::Polygon(geom.as_ewkb()),
985-
GeometryT::MultiPoint(ref geom) => EwkbGeometry::MultiPoint(geom.as_ewkb()),
986-
GeometryT::MultiLineString(ref geom) => EwkbGeometry::MultiLineString(geom.as_ewkb()),
987-
GeometryT::MultiPolygon(ref geom) => EwkbGeometry::MultiPolygon(geom.as_ewkb()),
988-
GeometryT::GeometryCollection(ref geom) => EwkbGeometry::GeometryCollection(geom.as_ewkb()),
989-
}
990-
}
964+
impl<'a, P> AsEwkbGeometry<'a> for GeometryT<P>
965+
where P: 'a + postgis::Point + EwkbRead + AsEwkbPoint<'a>
966+
{
967+
type PointType = P;
968+
type PointIter = Iter<'a, P>;
969+
type MultiPointType = MultiPointT<P>;
970+
type LineType = LineStringT<P>;
971+
type LineIter = Iter<'a, Self::LineType>;
972+
type MultiLineType = MultiLineStringT<P>;
973+
type PolyType = PolygonT<P>;
974+
type PolyIter = Iter<'a, Self::PolyType>;
975+
type MultiPolyType = MultiPolygonT<P>;
976+
type GeomType = GeometryT<P>;
977+
type GeomIter = Iter<'a, Self::GeomType>;
978+
type GeomCollection = GeometryCollectionT<P>;
979+
fn as_ewkb(&'a self) -> EwkbGeometry<'a, Self::PointType, Self::PointIter, Self::MultiPointType, Self::LineType, Self::LineIter, Self::MultiLineType, Self::PolyType, Self::PolyIter, Self::MultiPolyType, Self::GeomType, Self::GeomIter, Self::GeomCollection> {
980+
match *self {
981+
GeometryT::Point(ref geom) => EwkbGeometry::Point(geom.as_ewkb()),
982+
GeometryT::LineString(ref geom) => EwkbGeometry::LineString(geom.as_ewkb()),
983+
GeometryT::Polygon(ref geom) => EwkbGeometry::Polygon(geom.as_ewkb()),
984+
GeometryT::MultiPoint(ref geom) => EwkbGeometry::MultiPoint(geom.as_ewkb()),
985+
GeometryT::MultiLineString(ref geom) => EwkbGeometry::MultiLineString(geom.as_ewkb()),
986+
GeometryT::MultiPolygon(ref geom) => EwkbGeometry::MultiPolygon(geom.as_ewkb()),
987+
GeometryT::GeometryCollection(ref geom) => EwkbGeometry::GeometryCollection(geom.as_ewkb()),
991988
}
992-
)
989+
}
993990
}
994991

995-
impl_as_ewkb_geometry!(Point);
996-
impl_as_ewkb_geometry!(PointZ);
997-
impl_as_ewkb_geometry!(PointM);
998-
impl_as_ewkb_geometry!(PointZM);
999-
1000992
/// OGC Geometry type
1001993
pub type Geometry = GeometryT<Point>;
1002994
/// OGC GeometryZ type
@@ -1401,7 +1393,7 @@ fn test_geometrycollection_read() {
14011393
// SELECT 'GeometryCollection(POINT (10 10),POINT (30 30),LINESTRING (15 15, 20 20))'::geometry
14021394
let ewkb = hex_to_vec("01070000000300000001010000000000000000002440000000000000244001010000000000000000003E400000000000003E400102000000020000000000000000002E400000000000002E4000000000000034400000000000003440");
14031395
let geom = GeometryCollectionT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1404-
assert_eq!(format!("{:?}", geom), "GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })] }");
1396+
assert_eq!(format!("{:?}", geom), "GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })], srid: None }");
14051397
}
14061398

14071399
#[test]
@@ -1433,7 +1425,7 @@ fn test_geometry_read() {
14331425
// SELECT 'GeometryCollection(POINT (10 10),POINT (30 30),LINESTRING (15 15, 20 20))'::geometry
14341426
let ewkb = hex_to_vec("01070000000300000001010000000000000000002440000000000000244001010000000000000000003E400000000000003E400102000000020000000000000000002E400000000000002E4000000000000034400000000000003440");
14351427
let geom = GeometryT::<Point>::read_ewkb(&mut ewkb.as_slice()).unwrap();
1436-
assert_eq!(format!("{:?}", geom), "GeometryCollection(GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })] })");
1428+
assert_eq!(format!("{:?}", geom), "GeometryCollection(GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })], srid: None })");
14371429
}
14381430

14391431
#[test]

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
//! }
3636
//! ```
3737
38+
#![feature(underscore_lifetimes)]
3839
#[macro_use(accepts, to_sql_checked)]
3940
extern crate postgres;
4041
extern crate byteorder;

src/postgis.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//
44

55
use types::{Point, LineString, Polygon};
6-
use ewkb::{self, EwkbRead, EwkbWrite, AsEwkbPoint, AsEwkbLineString, AsEwkbPolygon, AsEwkbMultiPoint, AsEwkbMultiLineString, AsEwkbMultiPolygon, AsEwkbGeometry};
6+
use ewkb::{self, EwkbRead, EwkbWrite, AsEwkbPoint, AsEwkbLineString, AsEwkbPolygon, AsEwkbMultiPoint, AsEwkbMultiLineString, AsEwkbMultiPolygon, AsEwkbGeometry, AsEwkbGeometryCollection};
77
use twkb::{self, TwkbGeom};
88
use std::io::Cursor;
99
use postgres::types::{Type, IsNull, ToSql, FromSql, BYTEA};
@@ -163,10 +163,10 @@ impl<P> FromSql for ewkb::GeometryT<P>
163163
accepts_geography!();
164164
}
165165

166-
// NOTE: Implement once for each point type to avoid trait lifetime constraints
166+
// NOTE: Implement once per point type because AsEwkbPoint<'a> doesn't live long enough for ToSql
167167
macro_rules! impl_geometry_to_sql {
168168
($ptype:path) => (
169-
impl<'a> ToSql for ewkb::GeometryT<$ptype> {
169+
impl ToSql for ewkb::GeometryT<$ptype> {
170170
fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
171171
self.as_ewkb().write_ewkb(out)?;
172172
Ok(IsNull::No)
@@ -183,6 +183,7 @@ impl_geometry_to_sql!(ewkb::PointZ);
183183
impl_geometry_to_sql!(ewkb::PointM);
184184
impl_geometry_to_sql!(ewkb::PointZM);
185185

186+
186187
impl<P> FromSql for ewkb::GeometryCollectionT<P>
187188
where P: Point + EwkbRead
188189
{
@@ -194,6 +195,18 @@ impl<P> FromSql for ewkb::GeometryCollectionT<P>
194195
accepts_geography!();
195196
}
196197

198+
impl<'a, P> ToSql for ewkb::GeometryCollectionT<P>
199+
where P: Point + EwkbRead
200+
{
201+
fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
202+
self.as_ewkb().write_ewkb(out)?;
203+
Ok(IsNull::No)
204+
}
205+
206+
to_sql_checked!();
207+
accepts_geography!();
208+
}
209+
197210

198211
// --- TWKB ---
199212

0 commit comments

Comments
 (0)