use crate::system;
use abi_stable::std_types::{RString, RVec};
use abi_stable::StableAbi;
use tarantool::datetime::Datetime;
use tarantool::decimal::Decimal;
use tarantool::ffi::datetime::datetime;
use tarantool::uuid::Uuid;
#[derive(StableAbi)]
#[repr(C)]
pub struct RawDecimal {
pub digits: i32,
pub exponent: i32,
pub bits: u8,
pub lsu: [u16; tarantool::ffi::decimal::DECNUMUNITS as _],
}
impl From<RawDecimal> for tarantool::ffi::decimal::decNumber {
fn from(value: RawDecimal) -> Self {
tarantool::ffi::decimal::decNumber {
digits: value.digits,
exponent: value.exponent,
bits: value.bits,
lsu: value.lsu,
}
}
}
impl From<tarantool::ffi::decimal::decNumber> for RawDecimal {
fn from(value: tarantool::ffi::decimal::decNumber) -> Self {
RawDecimal {
digits: value.digits,
exponent: value.exponent,
bits: value.bits,
lsu: value.lsu,
}
}
}
#[derive(StableAbi)]
#[repr(C)]
pub struct RawDatetime {
pub epoch: f64,
pub nsec: i32,
pub tzoffset: i16,
pub tzindex: i16,
}
impl From<RawDatetime> for tarantool::ffi::datetime::datetime {
fn from(dt: RawDatetime) -> Self {
tarantool::ffi::datetime::datetime {
epoch: dt.epoch,
nsec: dt.nsec,
tzoffset: dt.tzoffset,
tzindex: dt.tzindex,
}
}
}
impl From<tarantool::ffi::datetime::datetime> for RawDatetime {
fn from(dt: datetime) -> Self {
Self {
epoch: dt.epoch,
nsec: dt.nsec,
tzoffset: dt.tzoffset,
tzindex: dt.tzindex,
}
}
}
#[derive(StableAbi)]
#[repr(C)]
pub enum SqlValueInner {
Boolean(bool),
Decimal(RawDecimal),
Double(f64),
Datetime(RawDatetime),
Integer(i64),
Null,
String(RString),
#[deprecated]
Unsigned(u64),
Array(RVec<SqlValue>),
Uuid([u8; 16]),
}
#[derive(StableAbi)]
#[repr(C)]
pub struct SqlValue(SqlValueInner);
impl SqlValue {
pub fn into_inner(self) -> SqlValueInner {
self.0
}
pub fn boolean(b: bool) -> Self {
SqlValue(SqlValueInner::Boolean(b))
}
pub fn decimal(dec: tarantool::decimal::Decimal) -> Self {
let dec = dec.into_raw();
SqlValue(SqlValueInner::Decimal(RawDecimal::from(dec)))
}
pub fn double(d: f64) -> Self {
SqlValue(SqlValueInner::Double(d))
}
pub fn datetime(dt: tarantool::datetime::Datetime) -> Self {
SqlValue(SqlValueInner::Datetime(RawDatetime::from(dt.as_ffi_dt())))
}
pub fn integer(i: i64) -> Self {
SqlValue(SqlValueInner::Integer(i))
}
pub fn null() -> Self {
SqlValue(SqlValueInner::Null)
}
pub fn string(s: impl Into<String>) -> Self {
SqlValue(SqlValueInner::String(RString::from(s.into())))
}
#[deprecated]
#[allow(deprecated)]
pub fn unsigned(u: u64) -> Self {
SqlValue(SqlValueInner::Unsigned(u))
}
pub fn array(arr: impl Into<Vec<Self>>) -> Self {
SqlValue(SqlValueInner::Array(RVec::from(arr.into())))
}
pub fn uuid(uuid: system::tarantool::uuid::Uuid) -> Self {
SqlValue(SqlValueInner::Uuid(*uuid.as_bytes()))
}
}
impl From<bool> for SqlValue {
fn from(b: bool) -> Self {
SqlValue::boolean(b)
}
}
impl From<Decimal> for SqlValue {
fn from(dec: Decimal) -> Self {
SqlValue::decimal(dec)
}
}
macro_rules! impl_float {
($t:ty) => {
impl From<$t> for SqlValue {
fn from(f: $t) -> Self {
SqlValue::double(f as f64)
}
}
};
}
impl_float!(f32);
impl_float!(f64);
impl From<Datetime> for SqlValue {
fn from(dt: Datetime) -> Self {
SqlValue::datetime(dt)
}
}
macro_rules! impl_int {
($t:ty) => {
impl From<$t> for SqlValue {
fn from(i: $t) -> Self {
SqlValue::integer(i as i64)
}
}
};
}
impl_int!(i8);
impl_int!(i16);
impl_int!(i32);
impl_int!(i64);
impl_int!(isize);
impl_int!(i128);
impl_int!(u8);
impl_int!(u16);
impl_int!(u32);
impl_int!(u64);
impl_int!(usize);
impl_int!(u128);
impl<T: Into<SqlValue>> From<Option<T>> for SqlValue {
fn from(opt: Option<T>) -> Self {
match opt {
None => SqlValue::null(),
Some(t) => t.into(),
}
}
}
impl From<String> for SqlValue {
fn from(s: String) -> Self {
SqlValue::string(s)
}
}
impl From<&str> for SqlValue {
fn from(s: &str) -> Self {
SqlValue::string(s)
}
}
impl<T: Into<SqlValue>> From<Vec<T>> for SqlValue {
fn from(vec: Vec<T>) -> Self {
let array: Vec<_> = vec.into_iter().map(|el| el.into()).collect();
SqlValue::array(array)
}
}
impl<T: Into<SqlValue> + Clone> From<&[T]> for SqlValue {
fn from(slice: &[T]) -> Self {
let array: Vec<_> = slice.iter().map(|el| el.clone().into()).collect();
SqlValue::array(array)
}
}
impl<T: Into<SqlValue>, const N: usize> From<[T; N]> for SqlValue {
fn from(slice: [T; N]) -> Self {
let array: Vec<_> = slice.into_iter().map(|el| el.into()).collect();
SqlValue::array(array)
}
}
impl From<Uuid> for SqlValue {
fn from(uuid: Uuid) -> Self {
SqlValue::uuid(uuid)
}
}