Skip to content

Commit 1d20769

Browse files
author
AGAEV Denis E
committed
Add additional types
1 parent 107d9f6 commit 1d20769

File tree

4 files changed

+197
-13
lines changed

4 files changed

+197
-13
lines changed

Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,3 @@ postgres-types = { git = "https://github.com/chandr-andr/rust-postgres.git", ver
3636
"derive",
3737
] }
3838
postgres-protocol = { git = "https://github.com/chandr-andr/rust-postgres.git", version = "*" }
39-

src/additional_types.rs

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
use std::{f64::consts::PI, fmt::Debug};
2+
13
use macaddr::{MacAddr6, MacAddr8};
4+
use itertools::Itertools;
5+
use geo_types::{coord, Coord, CoordNum, Line, Polygon};
6+
use byteorder::{ReadBytesExt, BigEndian};
27
use tokio_postgres::types::{FromSql, Type};
38

49
macro_rules! build_additional_rust_type {
@@ -60,3 +65,150 @@ impl<'a> FromSql<'a> for RustMacAddr8 {
6065
true
6166
}
6267
}
68+
69+
build_additional_rust_type!(RustLine, Line);
70+
build_additional_rust_type!(RustPolygon, Polygon);
71+
72+
impl<'a> FromSql<'a> for RustLine {
73+
fn from_sql(
74+
_ty: &Type,
75+
raw: &'a [u8],
76+
) -> Result<RustLine, Box<dyn std::error::Error + Sync + Send>> {
77+
if raw.len() == 4 {
78+
let mut vec_raw: Vec<u8> = vec![];
79+
vec_raw.extend_from_slice(raw);
80+
let mut buf: &[u8] = vec_raw.as_slice();
81+
82+
let x1 = buf.read_f64::<BigEndian>()?;
83+
let y1 = buf.read_f64::<BigEndian>()?;
84+
let first_coord: Coord<f64> = coord!(x: x1, y: y1);
85+
86+
let x2 = buf.read_f64::<BigEndian>()?;
87+
let y2 = buf.read_f64::<BigEndian>()?;
88+
let second_coord = coord!(x: x2, y: y2);
89+
90+
let new_line = Line::new(first_coord, second_coord);
91+
return Ok(RustLine::new(new_line));
92+
}
93+
Err("Cannot convert PostgreSQL LINE into rust Line".into())
94+
}
95+
96+
fn accepts(_ty: &Type) -> bool {
97+
true
98+
}
99+
}
100+
101+
// impl<'a> FromSql<'a> for RustPolygon {
102+
// fn from_sql(
103+
// _ty: &Type,
104+
// raw: &'a [u8],
105+
// ) -> Result<RustPolygon, Box<dyn std::error::Error + Sync + Send>> {
106+
// if raw.len() % 2 == 0 {
107+
// let mut vec_raw: Vec<u8> = vec![];
108+
// vec_raw.extend_from_slice(raw);
109+
110+
// for (x, y) in vec_raw.tuple_windows() {
111+
// let coord = coord!(x: x, y: y);
112+
// }
113+
114+
// let new_polygon = Polygon::new(exterior, interiors)
115+
// return Ok(RustPolygon::new(new_polygon));
116+
// }
117+
// Err("Cannot convert PostgreSQL POLYGON into rust Polygon".into())
118+
// }
119+
120+
// fn accepts(_ty: &Type) -> bool {
121+
// true
122+
// }
123+
// }
124+
125+
126+
// add macro for creating circles
127+
128+
#[derive(Eq, PartialEq, Clone, Copy, Debug,Hash)]
129+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
130+
pub struct Circle<T: CoordNum = f64> {
131+
center: Coord<T>,
132+
radius: T,
133+
}
134+
135+
impl<T: CoordNum> Circle<T> {
136+
pub fn new(x: T, y: T, r: T) -> Self {
137+
Self {center: Coord::new(x, y), radius: r}
138+
}
139+
140+
pub fn center(self) -> Coord<T> {
141+
self.center
142+
}
143+
144+
pub fn set_center(&mut self, center: Coord<T>) -> &mut Self {
145+
self.center = center;
146+
self
147+
}
148+
149+
pub fn center_mut(&mut self) -> &mut Coord<T> {
150+
&mut self.center
151+
}
152+
153+
pub fn radius(self) -> T {
154+
self.radius
155+
}
156+
157+
pub fn set_radius(&mut self, radius: T) -> &mut Self {
158+
self.radius = radius;
159+
self
160+
}
161+
162+
pub fn radius_mut(&mut self) -> &mut T {
163+
&mut self.radius
164+
}
165+
}
166+
167+
impl<T: CoordNum> Circle<T> {
168+
pub fn area(self) -> T {
169+
PI * self.radius * self.radius
170+
}
171+
pub fn perimeter(self) -> T {
172+
2.0 * PI * self.radius
173+
}
174+
175+
pub fn contains(self, point: &Coord<T>) -> bool {
176+
self.center.distance_to(point) <= self.radius
177+
}
178+
179+
pub fn intersects(self, other: &Self) -> bool {
180+
self.center.distance_to(&other.center) <= self.radius + other.radius
181+
}
182+
}
183+
184+
impl<T: CoordNum> Default for Circle<T> {
185+
fn default() -> Self {
186+
let default_center = Coord::default();
187+
Self {center: default_center, radius: 0.0}
188+
}
189+
}
190+
191+
impl<'a> FromSql<'a> for Circle {
192+
fn from_sql(
193+
_ty: &Type,
194+
raw: &'a [u8],
195+
) -> Result<Circle, Box<dyn std::error::Error + Sync + Send>> {
196+
if raw.len() == 3 {
197+
let mut vec_raw: Vec<u8> = vec![];
198+
vec_raw.extend_from_slice(raw);
199+
let mut buf: &[u8] = vec_raw.as_slice();
200+
201+
let x = buf.read_f64::<BigEndian>()?;
202+
let y = buf.read_f64::<BigEndian>()?;
203+
let r = buf.read_f64::<BigEndian>()?;
204+
205+
let new_circle = Circle::new(x, y, r);
206+
return Ok(new_circle);
207+
}
208+
Err("Cannot convert PostgreSQL CIRCLE into rust Circle".into())
209+
}
210+
211+
fn accepts(_ty: &Type) -> bool {
212+
true
213+
}
214+
}

src/value_converter.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,3 +818,36 @@ pub fn build_python_from_serde_value(
818818
Value::Null => Ok(py.None()),
819819
}
820820
}
821+
822+
pub fn box_from_sql(mut buf: &[u8]) -> Result<Box, StdBox<dyn Error + Sync + Send>> {
823+
let x1 = buf.read_f64::<BigEndian>()?;
824+
let y1 = buf.read_f64::<BigEndian>()?;
825+
let x2 = buf.read_f64::<BigEndian>()?;
826+
let y2 = buf.read_f64::<BigEndian>()?;
827+
if !buf.is_empty() {
828+
return Err("invalid buffer size".into());
829+
}
830+
let num_fields = postgres_types::private::read_be_i32(&mut buf).map_err(|err| {
831+
RustPSQLDriverError::RustToPyValueConversionError(format!(
832+
"Cannot read bytes data from PostgreSQL: {err}"
833+
))
834+
})?;
835+
Ok(Box {
836+
upper_right: Point { x: x1, y: y1 },
837+
lower_left: Point { x: x2, y: y2 },
838+
})
839+
}
840+
841+
pub fn box_from_sql(mut buf: &[u8]) -> Result<Box, StdBox<dyn Error + Sync + Send>> {
842+
let x1 = buf.read_f64::<BigEndian>()?;
843+
let y1 = buf.read_f64::<BigEndian>()?;
844+
let x2 = buf.read_f64::<BigEndian>()?;
845+
let y2 = buf.read_f64::<BigEndian>()?;
846+
if !buf.is_empty() {
847+
return Err("invalid buffer size".into());
848+
}
849+
Ok(Box {
850+
upper_right: Point { x: x1, y: y1 },
851+
lower_left: Point { x: x2, y: y2 },
852+
})
853+
}

0 commit comments

Comments
 (0)