use std::collections::HashMap;
use std::time::Duration;
use bigdecimal::BigDecimal;
use chrono::{
DateTime,
NaiveDate,
NaiveDateTime,
NaiveTime,
Utc,
};
use num_bigint::BigInt;
use serde::Serialize;
use serde::de::DeserializeOwned;
use url::Url;
use qubit_datatype::DataType;
use super::value::Value;
use crate::value_error::{
ValueError,
ValueResult,
};
macro_rules! impl_get_value {
($(#[$attr:meta])* copy: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&self) -> ValueResult<$type> {
match self {
Value::$variant(v) => Ok(*v),
Value::Empty(dt) if *dt == $data_type => Err(ValueError::NoValue),
Value::Empty(dt) => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: *dt,
}),
_ => 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 {
Value::$variant(v) => {
let conv_fn: fn(&_) -> $ret_type = $conversion;
Ok(conv_fn(v))
},
Value::Empty(dt) if *dt == $data_type => Err(ValueError::NoValue),
Value::Empty(dt) => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: *dt,
}),
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_set_value {
($(#[$attr:meta])* copy: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&mut self, value: $type) -> ValueResult<()> {
*self = Value::$variant(value);
Ok(())
}
};
($(#[$attr:meta])* owned: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[inline]
pub fn $method(&mut self, value: $type) -> ValueResult<()> {
*self = Value::$variant(value);
Ok(())
}
};
}
impl Value {
impl_get_value! {
copy: get_bool, Bool, bool, DataType::Bool
}
impl_get_value! {
copy: get_char, Char, char, DataType::Char
}
impl_get_value! {
copy: get_int8, Int8, i8, DataType::Int8
}
impl_get_value! {
copy: get_int16, Int16, i16, DataType::Int16
}
impl_get_value! {
copy: get_int32, Int32, i32, DataType::Int32
}
impl_get_value! {
copy: get_int64, Int64, i64, DataType::Int64
}
impl_get_value! {
copy: get_int128, Int128, i128, DataType::Int128
}
impl_get_value! {
copy: get_uint8, UInt8, u8, DataType::UInt8
}
impl_get_value! {
copy: get_uint16, UInt16, u16, DataType::UInt16
}
impl_get_value! {
copy: get_uint32, UInt32, u32, DataType::UInt32
}
impl_get_value! {
copy: get_uint64, UInt64, u64, DataType::UInt64
}
impl_get_value! {
copy: get_uint128, UInt128, u128, DataType::UInt128
}
impl_get_value! {
copy: get_float32, Float32, f32, DataType::Float32
}
impl_get_value! {
copy: get_float64, Float64, f64, DataType::Float64
}
impl_get_value! {
ref: get_string, String, &str, DataType::String, |s: &String| s.as_str()
}
impl_get_value! {
copy: get_date, Date, NaiveDate, DataType::Date
}
impl_get_value! {
copy: get_time, Time, NaiveTime, DataType::Time
}
impl_get_value! {
copy: get_datetime, DateTime, NaiveDateTime, DataType::DateTime
}
impl_get_value! {
copy: get_instant, Instant, DateTime<Utc>, DataType::Instant
}
impl_get_value! {
ref: get_biginteger, BigInteger, BigInt, DataType::BigInteger, |v: &BigInt| v.clone()
}
impl_get_value! {
ref: get_bigdecimal, BigDecimal, BigDecimal, DataType::BigDecimal, |v: &BigDecimal| v.clone()
}
impl_set_value! {
copy: set_bool, Bool, bool, DataType::Bool
}
impl_set_value! {
copy: set_char, Char, char, DataType::Char
}
impl_set_value! {
copy: set_int8, Int8, i8, DataType::Int8
}
impl_set_value! {
copy: set_int16, Int16, i16, DataType::Int16
}
impl_set_value! {
copy: set_int32, Int32, i32, DataType::Int32
}
impl_set_value! {
copy: set_int64, Int64, i64, DataType::Int64
}
impl_set_value! {
copy: set_int128, Int128, i128, DataType::Int128
}
impl_set_value! {
copy: set_uint8, UInt8, u8, DataType::UInt8
}
impl_set_value! {
copy: set_uint16, UInt16, u16, DataType::UInt16
}
impl_set_value! {
copy: set_uint32, UInt32, u32, DataType::UInt32
}
impl_set_value! {
copy: set_uint64, UInt64, u64, DataType::UInt64
}
impl_set_value! {
copy: set_uint128, UInt128, u128, DataType::UInt128
}
impl_set_value! {
copy: set_float32, Float32, f32, DataType::Float32
}
impl_set_value! {
copy: set_float64, Float64, f64, DataType::Float64
}
impl_set_value! {
owned: set_string, String, String, DataType::String
}
impl_set_value! {
copy: set_date, Date, NaiveDate, DataType::Date
}
impl_set_value! {
copy: set_time, Time, NaiveTime, DataType::Time
}
impl_set_value! {
copy: set_datetime, DateTime, NaiveDateTime, DataType::DateTime
}
impl_set_value! {
copy: set_instant, Instant, DateTime<Utc>, DataType::Instant
}
impl_set_value! {
owned: set_biginteger, BigInteger, BigInt, DataType::BigInteger
}
impl_set_value! {
owned: set_bigdecimal, BigDecimal, BigDecimal, DataType::BigDecimal
}
impl_get_value! {
copy: get_intsize, IntSize, isize, DataType::IntSize
}
impl_get_value! {
copy: get_uintsize, UIntSize, usize, DataType::UIntSize
}
impl_get_value! {
copy: get_duration, Duration, Duration, DataType::Duration
}
impl_get_value! {
ref: get_url, Url, Url, DataType::Url, |v: &Url| v.clone()
}
impl_get_value! {
ref: get_string_map, StringMap, HashMap<String, String>, DataType::StringMap,
|v: &HashMap<String, String>| v.clone()
}
impl_get_value! {
ref: get_json, Json, serde_json::Value, DataType::Json,
|v: &serde_json::Value| v.clone()
}
pub fn get_biginteger_ref(&self) -> ValueResult<&BigInt> {
match self {
Value::BigInteger(v) => Ok(v),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: DataType::BigInteger,
actual: self.data_type(),
}),
}
}
pub fn get_bigdecimal_ref(&self) -> ValueResult<&BigDecimal> {
match self {
Value::BigDecimal(v) => Ok(v),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: DataType::BigDecimal,
actual: self.data_type(),
}),
}
}
pub fn get_url_ref(&self) -> ValueResult<&Url> {
match self {
Value::Url(v) => Ok(v),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: DataType::Url,
actual: self.data_type(),
}),
}
}
pub fn get_string_map_ref(&self) -> ValueResult<&HashMap<String, String>> {
match self {
Value::StringMap(v) => Ok(v),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: DataType::StringMap,
actual: self.data_type(),
}),
}
}
pub fn get_json_ref(&self) -> ValueResult<&serde_json::Value> {
match self {
Value::Json(v) => Ok(v),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::TypeMismatch {
expected: DataType::Json,
actual: self.data_type(),
}),
}
}
impl_set_value! {
copy: set_intsize, IntSize, isize, DataType::IntSize
}
impl_set_value! {
copy: set_uintsize, UIntSize, usize, DataType::UIntSize
}
impl_set_value! {
copy: set_duration, Duration, Duration, DataType::Duration
}
impl_set_value! {
owned: set_url, Url, Url, DataType::Url
}
impl_set_value! {
owned: set_string_map, StringMap, HashMap<String, String>, DataType::StringMap
}
impl_set_value! {
owned: set_json, Json, serde_json::Value, DataType::Json
}
#[inline]
pub fn from_json_value(json: serde_json::Value) -> Self {
Value::Json(json)
}
pub fn from_serializable<T: Serialize>(value: &T) -> ValueResult<Self> {
let json = serde_json::to_value(value)
.map_err(|e| ValueError::JsonSerializationError(e.to_string()))?;
Ok(Value::Json(json))
}
pub fn deserialize_json<T: DeserializeOwned>(&self) -> ValueResult<T> {
match self {
Value::Json(v) => serde_json::from_value(v.clone())
.map_err(|e| ValueError::JsonDeserializationError(e.to_string())),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Json,
}),
}
}
}