Hi, I'm trying to write a diesel extension for postgis types. For that purpose I use rust-postgis library, because it already has all necessary types and transformations. I want to avoid a copy of data whenever possible and reuse datatypes from that library. I saw the implementation done here, but it doesn't look generic enough. So I started from defining the Point too, but did it like that
#[derive(Copy, Clone, PartialEq, FromSqlRow, AsExpression)]
#[sql_type = "Geometry"]
pub struct Point<P>
{
pub point: P,
}
Than there was no any problem yet for from_sql
method, yes I still may not understand some concepts, that is my second library on Rust, but it works for some cases:
impl<P> FromSql<Geometry, Pg> for Point<P>
where
P: postgis::Point+EwkbRead,
{
fn from_sql(bytes: Option<&<Pg as Backend>::RawValue>) -> deserialize::Result<Self> {
let bytes = not_none!(bytes);
let mut r = Cursor::new(bytes);
let geom = ewkb::GeometryT::read_ewkb(&mut r)?;
return match geom {
postgis::ewkb::GeometryT::Point(p) => Ok(Point { point: p }),
_ => Err(format!("Geometry is not a point").into()),
};
}
}
But problem appears when I try to implement the to_sql
method, because AsEwkbPoint
requires lifetime definition. I tried that code and code without lifetime definition and code with AsEwkbPoint<'_>, that is how I tried with defined lifetimes
impl<'a, P> ToSql<Geometry, Pg> for Point<P>
where
P: postgis::Point + AsEwkbPoint<'a>{
fn to_sql<W: Write>(&'a self, out: &mut Output<W, Pg>) -> serialize::Result {
self.point.as_ewkb().write_ewkb(out)?;
Ok(IsNull::No)
}
}
But I have that error
|
77 | fn to_sql<W: Write>(&'a self, out: &mut Output<W, Pg>) -> serialize::Result {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&Point<P>, &mut diesel::serialize::Output<'_, W, Pg>) -> std::result::Result<_, _>`
found fn pointer `fn(&'a Point<P>, &mut diesel::serialize::Output<'_, W, Pg>) -> std::result::Result<_, _>`
note: the anonymous lifetime #1 defined on the method body at 77:5...
--> src/lib.rs:77:5
|
77 | fn to_sql<W: Write>(&'a self, out: &mut Output<W, Pg>) -> serialize::Result {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 74:6
--> src/lib.rs:74:6
|
74 | impl<'a, P> ToSql<Geometry, Pg> for Point<P>
| ^^
I understand that if I define the struct which implements AsEwkbPoint
in Point
struct it'll work, but I don't want to do that in library, I believe that it should be defined in runnable code for specific table structure like so
#[derive(Insertable)]
#[table_name = "geometry_samples"]
struct NewGeometrySample {
point: postgis_diesel::Point<postgis::ewkb::Point>,
}
Please help to understand how to solve issues with lifetime like that one.