1use bytes::{BufMut, BytesMut};
2
3use crate::error::{Error, Result};
4use crate::types::{FromSql, Oid, ToSql};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct PgPoint {
9 pub x: f64,
10 pub y: f64,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq)]
15pub struct PgLine {
16 pub a: f64,
17 pub b: f64,
18 pub c: f64,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq)]
23pub struct PgLSeg {
24 pub start: PgPoint,
25 pub end: PgPoint,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq)]
30pub struct PgBox {
31 pub upper_right: PgPoint,
32 pub lower_left: PgPoint,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq)]
37pub struct PgCircle {
38 pub center: PgPoint,
39 pub radius: f64,
40}
41
42fn read_f64(buf: &[u8], off: usize) -> f64 {
44 f64::from_be_bytes([
45 buf[off],
46 buf[off + 1],
47 buf[off + 2],
48 buf[off + 3],
49 buf[off + 4],
50 buf[off + 5],
51 buf[off + 6],
52 buf[off + 7],
53 ])
54}
55
56impl ToSql for PgPoint {
59 fn oid(&self) -> Oid {
60 Oid::POINT
61 }
62
63 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
64 buf.put_f64(self.x);
65 buf.put_f64(self.y);
66 Ok(())
67 }
68}
69
70impl FromSql for PgPoint {
71 fn oid() -> Oid {
72 Oid::POINT
73 }
74
75 fn from_sql(buf: &[u8]) -> Result<Self> {
76 if buf.len() != 16 {
77 return Err(Error::Decode(format!(
78 "point: expected 16 bytes, got {}",
79 buf.len()
80 )));
81 }
82 Ok(PgPoint {
83 x: read_f64(buf, 0),
84 y: read_f64(buf, 8),
85 })
86 }
87}
88
89impl ToSql for PgLine {
92 fn oid(&self) -> Oid {
93 Oid::LINE
94 }
95
96 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
97 buf.put_f64(self.a);
98 buf.put_f64(self.b);
99 buf.put_f64(self.c);
100 Ok(())
101 }
102}
103
104impl FromSql for PgLine {
105 fn oid() -> Oid {
106 Oid::LINE
107 }
108
109 fn from_sql(buf: &[u8]) -> Result<Self> {
110 if buf.len() != 24 {
111 return Err(Error::Decode(format!(
112 "line: expected 24 bytes, got {}",
113 buf.len()
114 )));
115 }
116 Ok(PgLine {
117 a: read_f64(buf, 0),
118 b: read_f64(buf, 8),
119 c: read_f64(buf, 16),
120 })
121 }
122}
123
124impl ToSql for PgLSeg {
127 fn oid(&self) -> Oid {
128 Oid::LSEG
129 }
130
131 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
132 buf.put_f64(self.start.x);
133 buf.put_f64(self.start.y);
134 buf.put_f64(self.end.x);
135 buf.put_f64(self.end.y);
136 Ok(())
137 }
138}
139
140impl FromSql for PgLSeg {
141 fn oid() -> Oid {
142 Oid::LSEG
143 }
144
145 fn from_sql(buf: &[u8]) -> Result<Self> {
146 if buf.len() != 32 {
147 return Err(Error::Decode(format!(
148 "lseg: expected 32 bytes, got {}",
149 buf.len()
150 )));
151 }
152 Ok(PgLSeg {
153 start: PgPoint {
154 x: read_f64(buf, 0),
155 y: read_f64(buf, 8),
156 },
157 end: PgPoint {
158 x: read_f64(buf, 16),
159 y: read_f64(buf, 24),
160 },
161 })
162 }
163}
164
165impl ToSql for PgBox {
168 fn oid(&self) -> Oid {
169 Oid::PG_BOX
170 }
171
172 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
173 buf.put_f64(self.upper_right.x);
174 buf.put_f64(self.upper_right.y);
175 buf.put_f64(self.lower_left.x);
176 buf.put_f64(self.lower_left.y);
177 Ok(())
178 }
179}
180
181impl FromSql for PgBox {
182 fn oid() -> Oid {
183 Oid::PG_BOX
184 }
185
186 fn from_sql(buf: &[u8]) -> Result<Self> {
187 if buf.len() != 32 {
188 return Err(Error::Decode(format!(
189 "box: expected 32 bytes, got {}",
190 buf.len()
191 )));
192 }
193 Ok(PgBox {
194 upper_right: PgPoint {
195 x: read_f64(buf, 0),
196 y: read_f64(buf, 8),
197 },
198 lower_left: PgPoint {
199 x: read_f64(buf, 16),
200 y: read_f64(buf, 24),
201 },
202 })
203 }
204}
205
206impl ToSql for PgCircle {
209 fn oid(&self) -> Oid {
210 Oid::CIRCLE
211 }
212
213 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
214 buf.put_f64(self.center.x);
215 buf.put_f64(self.center.y);
216 buf.put_f64(self.radius);
217 Ok(())
218 }
219}
220
221impl FromSql for PgCircle {
222 fn oid() -> Oid {
223 Oid::CIRCLE
224 }
225
226 fn from_sql(buf: &[u8]) -> Result<Self> {
227 if buf.len() != 24 {
228 return Err(Error::Decode(format!(
229 "circle: expected 24 bytes, got {}",
230 buf.len()
231 )));
232 }
233 Ok(PgCircle {
234 center: PgPoint {
235 x: read_f64(buf, 0),
236 y: read_f64(buf, 8),
237 },
238 radius: read_f64(buf, 16),
239 })
240 }
241}