A PostGIS Diesel fork with simpler SRID support.
- Replace
srid
fields in all geometry types withconst generics
, for example, the definition ofPoint
:
// Original version
pub struct Point {
pub x: f64,
pub y: f64,
pub srid: u32,
}
// Forked version
pub struct Point<const SRID: u32> {
pub x: f64,
pub y: f64,
}
- Implement some useful traits for all geometry types, e.g.,
Default
,FromIterator
. - Implement
FromSql
andToSql
forGeometryContainer
. Polygon
is represented byline strings
instead of vectors of points.- Reorganize tests. Add
srid_test
and tests for 3D geometry types.
Geometry types with srid
field are more flexible, for example, types with different SRIDs
can be used together easily. However, it requires more work and caution:
- Every time we create a new instance, its
SRID
need to be set manually. FromIterator
is hard to implement properly. Because it needs to check whether theSRIDs
of all items are the same. In the original version, this trait is not implemented. The crate rust-postgis, which is an extension torust-postgres
, does supportFromIterator
, but theSRID
of generated instance is always zero, which is counter-intuitive.- It is hard to check whether a geometry type has the expected
srid
values. In contraction, our fork version makes it become a type constraint, which can be checked easily. For example, the implementation of traitFromSql
checks whether the rust sideSRID
(though const generic) is equal to theSRID
in the database side, if not, a deserialization error will be returned. See srid_test for more details.
Original:
use postgis_diesel::types::*;
struct NewGeometrySample {
point: Point,
polygon: polygon<Point>,
}
Fork:
use postgis_diesel::types::*;
struct Sample {
point: Point<4326>,
polygon: Polygon<4326, Point<4326>>,
}
Or we can import geometry types in gps
, which exports type aliases where all SRIDs
are 4326:
use postgis_diesel::gps::*;
struct Sample {
point: Point,
polygon: Polygon,
}
To crate an instance of Sample
in the original version (copied from integration_test.rs in the original repository):
fn new_line(points: Vec<(f64, f64)>) -> LineString<Point> {
let mut l_points = Vec::with_capacity(points.len());
for p in points {
l_points.push(Point {
x: p.0,
y: p.1,
srid: Option::Some(4326),
});
}
LineString {
points: l_points,
srid: Option::Some(4326),
}
}
fn new_sample() -> Sample {
Sample {
point: Point::new(0., 0., Some(4326)),
linestring: new_line(vec![(0., 0.), (1., 1.)]),,
}
}
In our fork version:
fn new_sample() -> Sample {
Sample {
point: Point::new(0., 0.),
linestring: vec![Point::new(0., 0.), Point::new(1., 1.)]
.into_iter()
.collect(),
}
}
See the original docment as there is no big differences between them.