Created
September 6, 2020 16:01
-
-
Save insanebaba/a15cf1375f4002d7b60b876180e25ab3 to your computer and use it in GitHub Desktop.
GeometryPoint Addition to arysn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use bytes::BytesMut; | |
// use geo_types::{Coordinate, Point}; | |
use postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; | |
use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor}; | |
use serde::ser::{Serialize, SerializeStruct, Serializer}; | |
use std::error::Error; | |
use std::fmt; | |
use std::ops::Deref; | |
use postgis::twkb::Point; | |
#[derive(PartialEq, Clone, Copy, Debug)] | |
pub struct GeometryPoint(Point); | |
impl GeometryPoint { | |
pub fn new(x: f64, y: f64) -> Self { | |
GeometryPoint(Point{x,y}) | |
} | |
} | |
impl Deref for GeometryPoint { | |
type Target = Point; | |
fn deref(&self) -> &Self::Target { | |
&self.0 | |
} | |
} | |
impl<'a> FromSql<'a> for GeometryPoint { | |
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> { | |
let point: Result<Point, Box<dyn Error + Sync + Send>> = FromSql::from_sql(ty, raw); | |
point.map(|point| GeometryPoint(point)) | |
} | |
fn accepts(ty: &Type) -> bool { | |
<GeometryPoint as FromSql>::accepts(ty) | |
} | |
} | |
impl ToSql for GeometryPoint { | |
fn to_sql( | |
&self, | |
ty: &Type, | |
out: &mut BytesMut, | |
) -> Result<IsNull, Box<dyn Error + Sync + Send>> { | |
ToSql::to_sql(&geo_types::Point::new(self.0.clone().x,self.0.clone().y), ty, out) | |
} | |
to_sql_checked!(); | |
fn accepts(ty: &Type) -> bool { | |
<geo_types::Point<f64> as ToSql>::accepts(ty) | |
} | |
} | |
impl Serialize for GeometryPoint { | |
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | |
where | |
S: Serializer, | |
{ | |
// 2 is the number of fields in the struct. | |
let mut state = serializer.serialize_struct("Point", 2)?; | |
state.serialize_field("x", &self.x)?; | |
state.serialize_field("y", &self.y)?; | |
state.end() | |
} | |
} | |
impl<'de> Deserialize<'de> for GeometryPoint { | |
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | |
where | |
D: Deserializer<'de>, | |
{ | |
enum Field { | |
X, | |
Y, | |
}; | |
impl<'de> Deserialize<'de> for Field { | |
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> | |
where | |
D: Deserializer<'de>, | |
{ | |
struct FieldVisitor; | |
impl<'de> Visitor<'de> for FieldVisitor { | |
type Value = Field; | |
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
formatter.write_str("`x` or `y` ") | |
} | |
fn visit_str<E>(self, value: &str) -> Result<Field, E> | |
where | |
E: de::Error, | |
{ | |
match value { | |
"x" => Ok(Field::X), | |
"y" => Ok(Field::Y), | |
_ => Err(de::Error::unknown_field(value, FIELDS)), | |
} | |
} | |
} | |
deserializer.deserialize_identifier(FieldVisitor) | |
} | |
} | |
struct GeometryPointVisitor; | |
impl<'de> Visitor<'de> for GeometryPointVisitor { | |
type Value = GeometryPoint; | |
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
formatter.write_str("struct GeometryPoint") | |
} | |
fn visit_seq<V>(self, mut seq: V) -> Result<GeometryPoint, V::Error> | |
where | |
V: SeqAccess<'de>, | |
{ | |
let x = seq | |
.next_element()? | |
.ok_or_else(|| de::Error::invalid_length(0, &self))?; | |
let y = seq | |
.next_element()? | |
.ok_or_else(|| de::Error::invalid_length(1, &self))?; | |
Ok(GeometryPoint::new(x, y)) | |
} | |
fn visit_map<V>(self, mut map: V) -> Result<GeometryPoint, V::Error> | |
where | |
V: MapAccess<'de>, | |
{ | |
let mut x = None; | |
let mut y = None; | |
while let Some(key) = map.next_key()? { | |
match key { | |
Field::X => { | |
if x.is_some() { | |
return Err(de::Error::duplicate_field("x")); | |
} | |
x = Some(map.next_value()?); | |
} | |
Field::Y => { | |
if y.is_some() { | |
return Err(de::Error::duplicate_field("y")); | |
} | |
y = Some(map.next_value()?); | |
} | |
} | |
} | |
let x = x.ok_or_else(|| de::Error::missing_field("x"))?; | |
let y = y.ok_or_else(|| de::Error::missing_field("y"))?; | |
Ok(GeometryPoint::new(x, y)) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["x", "y"]; | |
deserializer.deserialize_struct("GeometryPoint", FIELDS, GeometryPoint) | |
} | |
} | |
#[test] | |
fn test_ser_de() { | |
let point = Point::new(1.1234, -5.6789, None); | |
let s = serde_json::to_string(&point).unwrap(); | |
let d: Point = serde_json::from_str(&s).unwrap(); | |
assert_eq!(d, point); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment