use crate::api::ParamVec;
use crate::core::Value;
use super::types::StoolapValue;
use super::{
STOOLAP_TYPE_BLOB, STOOLAP_TYPE_BOOLEAN, STOOLAP_TYPE_FLOAT, STOOLAP_TYPE_INTEGER,
STOOLAP_TYPE_JSON, STOOLAP_TYPE_NULL, STOOLAP_TYPE_TEXT, STOOLAP_TYPE_TIMESTAMP,
};
pub(crate) unsafe fn ffi_value_to_rust(v: &StoolapValue) -> Value {
match v.value_type {
STOOLAP_TYPE_NULL => Value::null_unknown(),
STOOLAP_TYPE_INTEGER => Value::Integer(v.v.integer),
STOOLAP_TYPE_FLOAT => Value::Float(v.v.float64),
STOOLAP_TYPE_TEXT => {
let text = &v.v.text;
if text.ptr.is_null() || text.len < 0 {
Value::null_unknown()
} else if text.len == 0 {
Value::text("")
} else {
let slice = std::slice::from_raw_parts(text.ptr as *const u8, text.len as usize);
match std::str::from_utf8(slice) {
Ok(s) => Value::text(s),
Err(_) => Value::null_unknown(),
}
}
}
STOOLAP_TYPE_BOOLEAN => Value::Boolean(v.v.boolean != 0),
STOOLAP_TYPE_TIMESTAMP => {
let nanos = v.v.timestamp_nanos;
let secs = nanos.div_euclid(1_000_000_000);
let nsecs = nanos.rem_euclid(1_000_000_000) as u32;
match chrono::DateTime::from_timestamp(secs, nsecs) {
Some(dt) => Value::Timestamp(dt),
None => Value::null_unknown(),
}
}
STOOLAP_TYPE_JSON => {
let text = &v.v.text;
if text.ptr.is_null() || text.len < 0 {
Value::null_unknown()
} else if text.len == 0 {
Value::null_unknown()
} else {
let slice = std::slice::from_raw_parts(text.ptr as *const u8, text.len as usize);
match std::str::from_utf8(slice) {
Ok(s) => {
if serde_json::from_str::<serde_json::Value>(s).is_ok() {
Value::json(s)
} else {
Value::null_unknown()
}
}
Err(_) => Value::null_unknown(),
}
}
}
STOOLAP_TYPE_BLOB => {
let blob = &v.v.blob;
if blob.ptr.is_null() || blob.len < 0 {
Value::null_unknown()
} else if blob.len == 0 {
Value::vector(vec![])
} else {
let len = blob.len as usize;
if !len.is_multiple_of(4) {
Value::null_unknown()
} else {
let slice = std::slice::from_raw_parts(blob.ptr, len);
Value::vector_from_bytes(slice.into())
}
}
}
_ => Value::null_unknown(),
}
}
pub(crate) unsafe fn params_to_vec(params: *const StoolapValue, len: i32) -> ParamVec {
if params.is_null() || len <= 0 {
return ParamVec::new();
}
let slice = std::slice::from_raw_parts(params, len as usize);
slice.iter().map(|v| ffi_value_to_rust(v)).collect()
}