Skip to content

Commit 4bc8219

Browse files
committed
Fix Null, Inet, Mac
1 parent 59264b2 commit 4bc8219

File tree

3 files changed

+59
-37
lines changed

3 files changed

+59
-37
lines changed

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ lru = "0.12"
1313
serde = "1.0"
1414
thiserror = "1.0"
1515
strum = { version = "0.26", features = ["derive"] }
16+
cidr = "0.3.0"
17+
mac_address = "1.1.7"
1618

1719
[build-dependencies]
1820
bindgen = "0.70"

src/lib.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod crossdb_sys {
1313
mod column;
1414
mod de;
1515
mod error;
16+
mod params;
1617
mod row;
1718
mod statement;
1819
mod value;
@@ -27,10 +28,10 @@ pub use value::Value;
2728
use crossdb_sys::*;
2829
use lru::LruCache;
2930
use serde::de::{value::Error as DeError, DeserializeOwned};
30-
use std::ffi::{CStr, CString};
31+
use std::ffi::{c_void, CStr, CString};
3132
use std::fmt::Display;
3233
use std::num::NonZeroUsize;
33-
mod params;
34+
use std::slice::from_raw_parts;
3435

3536
pub fn version() -> &'static str {
3637
unsafe { CStr::from_ptr(xdb_version()).to_str().unwrap() }
@@ -193,14 +194,10 @@ impl Query {
193194
return None;
194195
}
195196
let mut values = Vec::with_capacity(self.column_count());
196-
for col in 0..self.column_count() {
197-
let value = Value::from_result(
198-
self.res.col_meta,
199-
row,
200-
col as u16,
201-
self.columns.datatype(col),
202-
);
203-
values.push(value);
197+
let iter = from_raw_parts(row, self.column_count()).iter().enumerate();
198+
for (i, ptr) in iter {
199+
let ptr = *ptr as *const c_void;
200+
values.push(Value::from_ptr(ptr, self.columns.datatype(i)));
204201
}
205202
Some(values)
206203
}

src/value.rs

+50-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
use crate::*;
2+
use cidr::{IpInet, Ipv4Inet, Ipv6Inet};
3+
use mac_address::MacAddress;
4+
use std::ffi::c_char;
5+
use std::net::{Ipv4Addr, Ipv6Addr};
6+
use std::ptr::read;
27

38
#[derive(Debug, Clone, PartialEq)]
49
pub enum Value<'a> {
@@ -13,8 +18,8 @@ pub enum Value<'a> {
1318
String(&'a str),
1419
Binary(&'a [u8]),
1520
Bool(bool),
16-
Inet([u8; 18]),
17-
Mac([u8; 6]),
21+
Inet(IpInet),
22+
Mac(MacAddress),
1823
}
1924

2025
impl Display for Value<'_> {
@@ -38,41 +43,59 @@ impl Display for Value<'_> {
3843
}
3944

4045
impl<'a> Value<'a> {
41-
// TODO: If you know the detailed format, you can access the pointer directly
42-
// https://crossdb.org/client/api-c/#xdb_column_int
43-
pub(crate) unsafe fn from_result(
44-
meta: u64,
45-
row: *mut xdb_row_t,
46-
col: u16,
47-
t: DataType,
48-
) -> Value<'a> {
46+
pub(crate) unsafe fn from_ptr(ptr: *const c_void, t: DataType) -> Self {
47+
if ptr.is_null() {
48+
return Self::Null;
49+
}
4950
match t {
5051
DataType::Null => Self::Null,
51-
DataType::TinyInt => Self::I8(xdb_column_int(meta, row, col) as _),
52+
DataType::TinyInt => Self::I8(read(ptr as *const i8)),
5253
DataType::UTinyInt => todo!(),
53-
DataType::SmallInt => Self::I16(xdb_column_int(meta, row, col) as _),
54+
DataType::SmallInt => Self::I16(read(ptr as *const i16)),
5455
DataType::USmallInt => todo!(),
55-
DataType::Int => Self::I32(xdb_column_int(meta, row, col) as _),
56+
DataType::Int => Self::I32(read(ptr as *const i32)),
5657
DataType::UInt => todo!(),
57-
DataType::BigInt => Self::I64(xdb_column_int64(meta, row, col)),
58+
DataType::BigInt => Self::I64(read(ptr as *const i64)),
5859
DataType::UBigInt => todo!(),
59-
DataType::Float => Self::F32(xdb_column_float(meta, row, col)),
60-
DataType::Double => Self::F64(xdb_column_double(meta, row, col)),
61-
DataType::Timestamp => Self::Timestamp(xdb_column_int64(meta, row, col)),
60+
DataType::Float => Self::F32(read(ptr as *const f32)),
61+
DataType::Double => Self::F64(read(ptr as *const f64)),
62+
DataType::Timestamp => Self::Timestamp(read(ptr as *const i64)),
6263
DataType::Char | DataType::VChar => {
63-
let ptr = xdb_column_str(meta, row, col);
64-
if ptr.is_null() {
65-
return Value::Null;
66-
}
67-
Value::String(CStr::from_ptr(ptr).to_str().unwrap())
64+
let str = CStr::from_ptr(ptr as *const c_char).to_str().unwrap();
65+
Self::String(str)
6866
}
6967
DataType::Binary | DataType::VBinary => {
70-
// xdb_column_blob(meta, row, col, pLen);
71-
todo!()
68+
let len = read((ptr as *const u8).offset(-2) as *const u16);
69+
let data = from_raw_parts(ptr as *const u8, len as usize);
70+
Self::Binary(data)
71+
}
72+
DataType::Bool => Self::Bool(*(ptr as *const i8) == 1),
73+
DataType::Inet => {
74+
let bytes = from_raw_parts(ptr as *const u8, 18);
75+
let mask = bytes[0];
76+
let family = bytes[1];
77+
match family {
78+
4 => {
79+
let mut buf = [0; 4];
80+
buf.copy_from_slice(&bytes[2..6]);
81+
let net = Ipv4Inet::new(Ipv4Addr::from(buf), mask).unwrap();
82+
Self::Inet(IpInet::V4(net))
83+
}
84+
6 => {
85+
let mut buf = [0; 16];
86+
buf.copy_from_slice(&bytes[2..18]);
87+
let net = Ipv6Inet::new(Ipv6Addr::from(buf), mask).unwrap();
88+
Self::Inet(IpInet::V6(net))
89+
}
90+
_ => unreachable!(),
91+
}
92+
}
93+
DataType::Mac => {
94+
let bytes = from_raw_parts(ptr as *const u8, 6);
95+
let address =
96+
MacAddress::new([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]]);
97+
Self::Mac(address)
7298
}
73-
DataType::Bool => Self::Bool(xdb_column_int(meta, row, col) == 1),
74-
DataType::Inet => todo!(),
75-
DataType::Mac => todo!(),
7699
DataType::Max => todo!(),
77100
}
78101
}

0 commit comments

Comments
 (0)