use crate::GeozeroGeometry;
use crate::wkb::{self, FromWkb};
use bytes::{BufMut, BytesMut};
use postgres_types::{FromSql, IsNull, ToSql, Type, to_sql_checked};
impl<T: FromWkb + Sized> FromSql<'_> for wkb::Decode<T> {
fn from_sql(_ty: &Type, raw: &[u8]) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
let mut rdr = std::io::Cursor::new(raw);
let geom = T::from_wkb(&mut rdr, wkb::WkbDialect::Ewkb)?;
Ok(wkb::Decode {
geometry: Some(geom),
})
}
fn from_sql_null(_ty: &Type) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
Ok(wkb::Decode { geometry: None })
}
fn accepts(ty: &Type) -> bool {
matches!(ty.name(), "geography" | "geometry")
}
}
impl FromSql<'_> for wkb::Ewkb<Vec<u8>> {
fn from_sql(_ty: &Type, raw: &[u8]) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
Ok(wkb::Ewkb(raw.to_vec()))
}
fn from_sql_null(_ty: &Type) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
Ok(wkb::Ewkb(Vec::new()))
}
fn accepts(ty: &Type) -> bool {
matches!(ty.name(), "geography" | "geometry")
}
}
impl<T: GeozeroGeometry + Sized> ToSql for wkb::Encode<T> {
fn to_sql(
&self,
_ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn std::error::Error + Sync + Send>> {
let pgout = &mut out.writer();
let mut writer = wkb::WkbWriter::with_opts(
pgout,
wkb::WkbDialect::Ewkb,
self.0.dims(),
self.0.srid(),
Vec::new(),
);
self.0.process_geom(&mut writer)?;
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
matches!(ty.name(), "geography" | "geometry")
}
to_sql_checked!();
}
#[macro_export]
macro_rules! impl_postgres_postgis_decode {
( $t:ty ) => {
impl postgres_types::FromSql<'_> for $t {
fn from_sql(
_ty: &postgres_types::Type,
raw: &[u8],
) -> std::result::Result<Self, Box<dyn std::error::Error + Sync + Send>> {
use $crate::wkb::FromWkb;
let mut rdr = std::io::Cursor::new(raw);
let geom = <$t>::from_wkb(&mut rdr, $crate::wkb::WkbDialect::Ewkb)?;
Ok(geom)
}
fn accepts(ty: &postgres_types::Type) -> bool {
match ty.name() {
"geography" | "geometry" => true,
_ => false,
}
}
}
};
}
#[macro_export]
macro_rules! impl_postgres_postgis_encode {
( $t:ty ) => {
impl<'a> postgres_types::ToSql for $t {
fn to_sql(
&self,
_ty: &postgres_types::Type,
out: &mut bytes::BytesMut,
) -> std::result::Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>>
{
use $crate::GeozeroGeometry;
use bytes::BufMut;
let pgout = &mut out.writer();
let mut writer = $crate::wkb::WkbWriter::with_opts(
pgout,
$crate::wkb::WkbDialect::Ewkb,
self.dims(),
self.srid(),
Vec::new(),
);
self.process_geom(&mut writer)?;
Ok(postgres_types::IsNull::No)
}
fn accepts(ty: &postgres_types::Type) -> bool {
match ty.name() {
"geography" | "geometry" => true,
_ => false,
}
}
postgres_types::to_sql_checked!();
}
};
}