Skip to content

Commit 2aa1b53

Browse files
authored
Merge pull request #27 from qaspen-python/feature/add_macaddr8_support
Added support for MacAddr8 type
2 parents 6903eb5 + ad4609c commit 2aa1b53

File tree

5 files changed

+161
-41
lines changed

5 files changed

+161
-41
lines changed

python/psqlpy/_internal/extra_types.pyi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,13 @@ class PyMacAddr6:
7272
### Parameters:
7373
- `value`: value for MACADDR field.
7474
"""
75+
76+
class PyMacAddr8:
77+
"""Represents MACADDR8 in PostgreSQL."""
78+
79+
def __init__(self, value: str) -> None:
80+
"""Construct new MacAddr8.
81+
82+
### Parameters:
83+
- `value`: value for MACADDR8 field.
84+
"""

python/psqlpy/extra_types.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
from ._internal.extra_types import BigInt, Integer, PyJSON, PyMacAddr6, PyUUID, SmallInt
1+
from ._internal.extra_types import (
2+
BigInt,
3+
Integer,
4+
PyJSON,
5+
PyMacAddr6,
6+
PyMacAddr8,
7+
PyUUID,
8+
SmallInt,
9+
)
210

311
__all__ = [
412
"SmallInt",
@@ -7,4 +15,5 @@
715
"PyUUID",
816
"PyJSON",
917
"PyMacAddr6",
18+
"PyMacAddr8",
1019
]

src/additional_types.rs

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
1-
use macaddr::MacAddr6;
1+
use macaddr::{MacAddr6, MacAddr8};
22
use tokio_postgres::types::{FromSql, Type};
33

4-
#[derive(Debug)]
5-
pub struct RustMacAddr6 {
6-
inner: MacAddr6,
7-
}
4+
macro_rules! build_additional_rust_type {
5+
($st_name:ident, $rust_type:ty) => {
6+
#[derive(Debug)]
7+
pub struct $st_name {
8+
inner: $rust_type,
9+
}
810

9-
impl RustMacAddr6 {
10-
#[must_use]
11-
pub fn new(inner: MacAddr6) -> Self {
12-
RustMacAddr6 { inner }
13-
}
11+
impl $st_name {
12+
#[must_use]
13+
pub fn new(inner: $rust_type) -> Self {
14+
$st_name { inner }
15+
}
1416

15-
#[must_use]
16-
pub fn inner(&self) -> &MacAddr6 {
17-
&self.inner
18-
}
17+
#[must_use]
18+
pub fn inner(&self) -> &$rust_type {
19+
&self.inner
20+
}
21+
}
22+
};
1923
}
2024

25+
build_additional_rust_type!(RustMacAddr6, MacAddr6);
26+
build_additional_rust_type!(RustMacAddr8, MacAddr8);
27+
2128
impl<'a> FromSql<'a> for RustMacAddr6 {
2229
fn from_sql(
2330
_ty: &Type,
@@ -34,3 +41,22 @@ impl<'a> FromSql<'a> for RustMacAddr6 {
3441
true
3542
}
3643
}
44+
45+
impl<'a> FromSql<'a> for RustMacAddr8 {
46+
fn from_sql(
47+
_ty: &Type,
48+
raw: &'a [u8],
49+
) -> Result<RustMacAddr8, Box<dyn std::error::Error + Sync + Send>> {
50+
if raw.len() == 8 {
51+
let new_mac_address = MacAddr8::new(
52+
raw[0], raw[1], raw[2], raw[3], raw[4], raw[5], raw[6], raw[7],
53+
);
54+
return Ok(RustMacAddr8::new(new_mac_address));
55+
}
56+
Err("Cannot convert PostgreSQL MACADDR8 into rust MacAddr8".into())
57+
}
58+
59+
fn accepts(_ty: &Type) -> bool {
60+
true
61+
}
62+
}

src/extra_types.rs

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::str::FromStr;
22

3-
use macaddr::MacAddr6;
3+
use macaddr::{MacAddr6, MacAddr8};
44
use pyo3::{pyclass, pymethods, types::PyModule, PyAny, PyResult, Python};
55
use serde_json::Value;
66
use uuid::Uuid;
@@ -95,30 +95,81 @@ impl PyJSON {
9595
}
9696
}
9797

98-
#[pyclass]
99-
#[derive(Clone)]
100-
pub struct PyMacAddr6 {
101-
inner: MacAddr6,
102-
}
98+
macro_rules! build_macaddr_type {
99+
($st_name:ident, $rust_type:ty) => {
100+
#[pyclass]
101+
#[derive(Clone)]
102+
pub struct $st_name {
103+
inner: $rust_type,
104+
}
103105

104-
impl PyMacAddr6 {
105-
#[must_use]
106-
pub fn inner(self) -> MacAddr6 {
107-
self.inner
108-
}
109-
}
106+
impl $st_name {
107+
#[must_use]
108+
pub fn inner(self) -> $rust_type {
109+
self.inner
110+
}
111+
}
110112

111-
#[pymethods]
112-
impl PyMacAddr6 {
113-
#[new]
114-
#[allow(clippy::missing_errors_doc)]
115-
pub fn new_macaddr6(value: &str) -> RustPSQLDriverPyResult<Self> {
116-
Ok(Self {
117-
inner: MacAddr6::from_str(value)?,
118-
})
119-
}
113+
#[pymethods]
114+
impl $st_name {
115+
#[new]
116+
#[allow(clippy::missing_errors_doc)]
117+
pub fn new_class(value: &str) -> RustPSQLDriverPyResult<Self> {
118+
Ok(Self {
119+
inner: <$rust_type>::from_str(value)?,
120+
})
121+
}
122+
}
123+
};
120124
}
121125

126+
build_macaddr_type!(PyMacAddr6, MacAddr6);
127+
build_macaddr_type!(PyMacAddr8, MacAddr8);
128+
129+
// #[pyclass]
130+
// #[derive(Clone)]
131+
// pub struct PyMacAddr6 {
132+
// inner: MacAddr6,
133+
// }
134+
135+
// impl PyMacAddr6 {
136+
// #[must_use]
137+
// pub fn inner(self) -> MacAddr6 {
138+
// self.inner
139+
// }
140+
// }
141+
142+
// #[pymethods]
143+
// impl PyMacAddr6 {
144+
// #[new]
145+
// #[allow(clippy::missing_errors_doc)]
146+
// pub fn new_macaddr6(value: &str) -> RustPSQLDriverPyResult<Self> {
147+
// Ok(Self {
148+
// inner: MacAddr6::from_str(value)?,
149+
// })
150+
// }
151+
// }
152+
153+
// #[pyclass]
154+
// #[derive(Clone)]
155+
// pub struct PyMacAddr8 {
156+
// inner: MacAddr8,
157+
// }
158+
159+
// impl PyMacAddr8 {
160+
// #[must_use]
161+
// pub fn inner(self) -> MacAddr8 {
162+
// self.inner
163+
// }
164+
// }
165+
166+
// #[pymethods]
167+
// impl PyMacAddr8 {
168+
// #[new]
169+
// #[allow(clippy::missing_errors_doc)]
170+
// pub fn new_macaddr8(value: &str) -> RustPSQLDriverPyResult<Self> {}
171+
// }
172+
122173
#[allow(clippy::module_name_repetitions)]
123174
#[allow(clippy::missing_errors_doc)]
124175
pub fn extra_types_module(_py: Python<'_>, pymod: &PyModule) -> PyResult<()> {
@@ -128,5 +179,6 @@ pub fn extra_types_module(_py: Python<'_>, pymod: &PyModule) -> PyResult<()> {
128179
pymod.add_class::<PyUUID>()?;
129180
pymod.add_class::<PyJSON>()?;
130181
pymod.add_class::<PyMacAddr6>()?;
182+
pymod.add_class::<PyMacAddr8>()?;
131183
Ok(())
132184
}

src/value_converter.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use chrono::{self, DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
2-
use macaddr::MacAddr6;
2+
use macaddr::{MacAddr6, MacAddr8};
33
use serde_json::{json, Map, Value};
44
use std::{fmt::Debug, net::IpAddr};
55
use uuid::Uuid;
@@ -19,9 +19,9 @@ use tokio_postgres::{
1919
};
2020

2121
use crate::{
22-
additional_types::RustMacAddr6,
22+
additional_types::{RustMacAddr6, RustMacAddr8},
2323
exceptions::rust_errors::{RustPSQLDriverError, RustPSQLDriverPyResult},
24-
extra_types::{BigInt, Integer, PyJSON, PyMacAddr6, PyUUID, SmallInt},
24+
extra_types::{BigInt, Integer, PyJSON, PyMacAddr6, PyMacAddr8, PyUUID, SmallInt},
2525
};
2626

2727
pub type QueryParameter = (dyn ToSql + Sync);
@@ -54,6 +54,7 @@ pub enum PythonDTO {
5454
PyTuple(Vec<PythonDTO>),
5555
PyJson(Value),
5656
PyMacAddr6(MacAddr6),
57+
PyMacAddr8(MacAddr8),
5758
}
5859

5960
impl PythonDTO {
@@ -188,6 +189,9 @@ impl ToSql for PythonDTO {
188189
PythonDTO::PyMacAddr6(pymacaddr) => {
189190
<&[u8] as ToSql>::to_sql(&pymacaddr.as_bytes(), ty, out)?;
190191
}
192+
PythonDTO::PyMacAddr8(pymacaddr) => {
193+
<&[u8] as ToSql>::to_sql(&pymacaddr.as_bytes(), ty, out)?;
194+
}
191195
PythonDTO::PyList(py_iterable) | PythonDTO::PyTuple(py_iterable) => {
192196
let mut items = Vec::new();
193197
for inner in py_iterable {
@@ -245,6 +249,7 @@ pub fn convert_parameters(parameters: &PyAny) -> RustPSQLDriverPyResult<Vec<Pyth
245249
///
246250
/// May return Err Result if python type doesn't have support yet
247251
/// or value of the type is incorrect.
252+
#[allow(clippy::too_many_lines)]
248253
pub fn py_to_rust(parameter: &PyAny) -> RustPSQLDriverPyResult<PythonDTO> {
249254
if parameter.is_none() {
250255
return Ok(PythonDTO::PyNone);
@@ -362,6 +367,12 @@ pub fn py_to_rust(parameter: &PyAny) -> RustPSQLDriverPyResult<PythonDTO> {
362367
));
363368
}
364369

370+
if parameter.is_instance_of::<PyMacAddr8>() {
371+
return Ok(PythonDTO::PyMacAddr8(
372+
parameter.extract::<PyMacAddr8>()?.inner(),
373+
));
374+
}
375+
365376
if let Ok(id_address) = parameter.extract::<IpAddr>() {
366377
return Ok(PythonDTO::PyIpAddress(id_address));
367378
}
@@ -494,8 +505,20 @@ pub fn postgres_to_py(
494505
}
495506
// Convert MACADDR into inner type for macaddr6, then into str
496507
Type::MACADDR => {
497-
let macaddr_ = row.try_get::<_, RustMacAddr6>(column_i)?;
498-
Ok(macaddr_.inner().to_string().to_object(py))
508+
let macaddr_ = row.try_get::<_, Option<RustMacAddr6>>(column_i)?;
509+
if let Some(macaddr_) = macaddr_ {
510+
Ok(macaddr_.inner().to_string().to_object(py))
511+
} else {
512+
Ok(py.None().to_object(py))
513+
}
514+
}
515+
Type::MACADDR8 => {
516+
let macaddr_ = row.try_get::<_, Option<RustMacAddr8>>(column_i)?;
517+
if let Some(macaddr_) = macaddr_ {
518+
Ok(macaddr_.inner().to_string().to_object(py))
519+
} else {
520+
Ok(py.None().to_object(py))
521+
}
499522
}
500523
_ => Err(RustPSQLDriverError::RustToPyValueConversionError(
501524
column.type_().to_string(),

0 commit comments

Comments
 (0)