1use crate::sql_types::*;
2use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
3use diesel::deserialize::{self, FromSql};
4use diesel::pg::Pg;
5use diesel::serialize::{self, IsNull, Output, ToSql};
6use std::io::prelude::*;
7use std::io::Cursor;
8
9#[derive(Debug, Clone, Copy, AsExpression, FromSqlRow, PartialEq)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11#[diesel(sql_type = Point)]
12pub struct PointXy(pub f64, pub f64);
13
14impl PointXy {
15 pub fn new(x: f64, y: f64) -> Self {
16 PointXy(x, y)
17 }
18}
19
20impl ToSql<Point, Pg> for PointXy {
21 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
22 let mut buf = Cursor::new(vec![]);
23 buf.write_f64::<NetworkEndian>(self.0)?;
24 buf.write_f64::<NetworkEndian>(self.1)?;
25 out.write_all(&buf.into_inner())?;
26 Ok(IsNull::No)
27 }
28}
29
30impl ToSql<Point, Pg> for (f64, f64) {
31 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
32 let mut buf = Cursor::new(vec![]);
33 buf.write_f64::<NetworkEndian>(self.0)?;
34 buf.write_f64::<NetworkEndian>(self.1)?;
35 out.write_all(&buf.into_inner())?;
36 Ok(IsNull::No)
37 }
38}
39
40impl FromSql<Point, Pg> for PointXy {
41 fn from_sql(
42 bytes: <Pg as diesel::backend::Backend>::RawValue<'_>,
43 ) -> deserialize::Result<Self> {
44 let (x, y) = <(f64, f64) as FromSql<Point, Pg>>::from_sql(bytes)?;
45 Ok(PointXy(x, y))
46 }
47}
48
49impl FromSql<Point, Pg> for (f64, f64) {
50 fn from_sql(
51 bytes: <Pg as diesel::backend::Backend>::RawValue<'_>,
52 ) -> deserialize::Result<Self> {
53 let bytes = bytes.as_bytes();
54 let mut buf = Cursor::new(bytes);
55 let x = buf
56 .read_f64::<NetworkEndian>()
57 .map_err(|err| diesel::result::Error::DeserializationError(Box::new(err)))?;
58 let y = buf
59 .read_f64::<NetworkEndian>()
60 .map_err(|err| diesel::result::Error::DeserializationError(Box::new(err)))?;
61 Ok((x, y))
62 }
63}