use bigdecimal::BigDecimal;
use chrono::{
DateTime,
NaiveDate,
NaiveDateTime,
NaiveTime,
Utc,
};
use num_bigint::BigInt;
use serde::{
Deserialize,
Serialize,
};
use std::collections::HashMap;
use std::time::Duration;
use url::Url;
use qubit_datatype::DataType;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum MultiValues {
Empty(DataType),
Bool(Vec<bool>),
Char(Vec<char>),
Int8(Vec<i8>),
Int16(Vec<i16>),
Int32(Vec<i32>),
Int64(Vec<i64>),
Int128(Vec<i128>),
UInt8(Vec<u8>),
UInt16(Vec<u16>),
UInt32(Vec<u32>),
UInt64(Vec<u64>),
UInt128(Vec<u128>),
IntSize(Vec<isize>),
UIntSize(Vec<usize>),
Float32(Vec<f32>),
Float64(Vec<f64>),
BigInteger(Vec<BigInt>),
BigDecimal(Vec<BigDecimal>),
String(Vec<String>),
Date(Vec<NaiveDate>),
Time(Vec<NaiveTime>),
DateTime(Vec<NaiveDateTime>),
Instant(Vec<DateTime<Utc>>),
Duration(Vec<Duration>),
Url(Vec<Url>),
StringMap(Vec<HashMap<String, String>>),
Json(Vec<serde_json::Value>),
}
macro_rules! impl_get_multi_values {
($(#[$attr:meta])* slice: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&self) -> ValueResult<&[$type]> {
match self {
MultiValues::$variant(v) => Ok(v),
MultiValues::Empty(dt) if *dt == $data_type => Ok(&[]),
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
($(#[$attr:meta])* vec: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&self) -> ValueResult<&[$type]> {
match self {
MultiValues::$variant(v) => Ok(v.as_slice()),
MultiValues::Empty(dt) if *dt == $data_type => Ok(&[]),
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_get_first_value {
($(#[$attr:meta])* copy: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&self) -> ValueResult<$type> {
match self {
MultiValues::$variant(v) if !v.is_empty() => Ok(v[0]),
MultiValues::$variant(_) => Err(ValueError::NoValue),
MultiValues::Empty(dt) if *dt == $data_type => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
($(#[$attr:meta])* ref: $method:ident, $variant:ident, $ret_type:ty, $data_type:expr, $conversion:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&self) -> ValueResult<$ret_type> {
match self {
MultiValues::$variant(v) if !v.is_empty() => {
let conv_fn: fn(&_) -> $ret_type = $conversion;
Ok(conv_fn(&v[0]))
},
MultiValues::$variant(_) => Err(ValueError::NoValue),
MultiValues::Empty(dt) if *dt == $data_type => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_add_single_value {
($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&mut self, value: $type) -> ValueResult<()> {
match self {
MultiValues::$variant(v) => {
v.push(value);
Ok(())
}
MultiValues::Empty(dt) if *dt == $data_type => {
*self = MultiValues::$variant(vec![value]);
Ok(())
}
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_add_multi_values {
($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&mut self, values: Vec<$type>) -> ValueResult<()> {
match self {
MultiValues::$variant(v) => {
v.extend(values);
Ok(())
}
MultiValues::Empty(dt) if *dt == $data_type => {
*self = MultiValues::$variant(values);
Ok(())
}
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_add_multi_values_slice {
($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&mut self, values: &[$type]) -> ValueResult<()> {
match self {
MultiValues::$variant(v) => {
v.extend_from_slice(values);
Ok(())
}
MultiValues::Empty(dt) if *dt == $data_type => {
*self = MultiValues::$variant(values.to_vec());
Ok(())
}
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_set_single_value {
($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
pub fn $method(&mut self, value: $type) -> ValueResult<()> {
*self = MultiValues::$variant(vec![value]);
Ok(())
}
};
}
macro_rules! impl_set_multi_values {
($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
pub fn $method(&mut self, values: Vec<$type>) -> ValueResult<()> {
*self = MultiValues::$variant(values);
Ok(())
}
};
}
macro_rules! impl_set_multi_values_slice {
($(#[$attr:meta])* $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
pub fn $method(&mut self, values: &[$type]) -> ValueResult<()> {
*self = MultiValues::$variant(values.to_vec());
Ok(())
}
};
}