postgres_types_extra/
pg_polygon.rs1use bytes::{Buf, BufMut};
2use postgres_types::{FromSql, IsNull, ToSql, Type, accepts, to_sql_checked};
3use std::{error::Error, fmt};
4
5use super::pg_point::PgPoint;
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct PgPolygon {
9 pub points: Vec<PgPoint>,
10}
11
12impl fmt::Display for PgPolygon {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 write!(
15 f,
16 "({})",
17 self.points
18 .iter()
19 .map(|p| p.to_string())
20 .collect::<Vec<_>>()
21 .join(",")
22 )
23 }
24}
25
26impl FromSql<'_> for PgPolygon {
27 fn from_sql(ty: &Type, mut raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
28 if ty.name() != "polygon" {
29 return Err("Unexpected type".into());
30 }
31 let npoints = raw.get_i32();
32 let mut points = Vec::with_capacity(npoints as usize);
33 for _ in 0..npoints {
34 let x = raw.get_f64();
35 let y = raw.get_f64();
36 points.push(PgPoint { x, y });
37 }
38 Ok(PgPolygon { points })
39 }
40
41 accepts!(POLYGON);
42}
43
44impl ToSql for PgPolygon {
45 fn to_sql(
46 &self,
47 ty: &Type,
48 out: &mut bytes::BytesMut,
49 ) -> Result<postgres_types::IsNull, Box<dyn Error + Sync + Send>>
50 where
51 Self: Sized,
52 {
53 if ty.name() != "polygon" {
54 return Err("Unexpected type".into());
55 }
56
57 let npoints: i32 = self.points.len().try_into()?;
58 out.put_i32(npoints);
59
60 for pt in &self.points {
61 out.put_f64(pt.x);
62 out.put_f64(pt.y);
63 }
64
65 Ok(IsNull::No)
66 }
67
68 accepts!(POLYGON);
69
70 to_sql_checked!();
71}