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::{
DataConversionOptions,
DataConvertTo,
DataConverter,
DataType,
};
use crate::value_error::ValueResult;
use crate::{
IntoValueDefault,
ValueError,
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
Empty(DataType),
Bool(bool),
Char(char),
Int8(i8),
Int16(i16),
Int32(i32),
Int64(i64),
Int128(i128),
UInt8(u8),
UInt16(u16),
UInt32(u32),
UInt64(u64),
UInt128(u128),
IntSize(isize),
UIntSize(usize),
Float32(f32),
Float64(f64),
BigInteger(BigInt),
BigDecimal(BigDecimal),
String(String),
Date(NaiveDate),
Time(NaiveTime),
DateTime(NaiveDateTime),
Instant(DateTime<Utc>),
Duration(Duration),
Url(Url),
StringMap(HashMap<String, String>),
Json(serde_json::Value),
}
use super::value_constructor::ValueConstructor;
use super::value_converter::ValueConverter;
use super::value_getter::ValueGetter;
use super::value_setter::ValueSetter;
impl Value {
#[inline]
pub fn new<T>(value: T) -> Self
where
Self: ValueConstructor<T>,
{
<Self as ValueConstructor<T>>::from_type(value)
}
#[inline]
pub fn get<T>(&self) -> ValueResult<T>
where
Self: ValueGetter<T>,
{
<Self as ValueGetter<T>>::get_value(self)
}
#[inline]
pub fn get_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
where
Self: ValueGetter<T>,
{
match self.get() {
Err(ValueError::NoValue) => Ok(default.into_value_default()),
result => result,
}
}
#[inline]
pub fn to<T>(&self) -> ValueResult<T>
where
Self: ValueConverter<T>,
{
<Self as ValueConverter<T>>::convert(self)
}
#[inline]
pub fn to_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
where
Self: ValueConverter<T>,
{
match self.to() {
Err(ValueError::NoValue) => Ok(default.into_value_default()),
result => result,
}
}
#[inline]
pub fn to_with<T>(&self, options: &DataConversionOptions) -> ValueResult<T>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
super::value_converters::convert_with_data_converter_with(self, options)
}
#[inline]
pub fn to_or_with<T>(
&self,
default: impl IntoValueDefault<T>,
options: &DataConversionOptions,
) -> ValueResult<T>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
match self.to_with(options) {
Err(ValueError::NoValue) => Ok(default.into_value_default()),
result => result,
}
}
#[inline]
pub fn set<T>(&mut self, value: T) -> ValueResult<()>
where
Self: ValueSetter<T>,
{
<Self as ValueSetter<T>>::set_value(self, value)
}
#[inline]
pub fn data_type(&self) -> DataType {
match self {
Value::Empty(dt) => *dt,
Value::Bool(_) => DataType::Bool,
Value::Char(_) => DataType::Char,
Value::Int8(_) => DataType::Int8,
Value::Int16(_) => DataType::Int16,
Value::Int32(_) => DataType::Int32,
Value::Int64(_) => DataType::Int64,
Value::Int128(_) => DataType::Int128,
Value::UInt8(_) => DataType::UInt8,
Value::UInt16(_) => DataType::UInt16,
Value::UInt32(_) => DataType::UInt32,
Value::UInt64(_) => DataType::UInt64,
Value::UInt128(_) => DataType::UInt128,
Value::Float32(_) => DataType::Float32,
Value::Float64(_) => DataType::Float64,
Value::String(_) => DataType::String,
Value::Date(_) => DataType::Date,
Value::Time(_) => DataType::Time,
Value::DateTime(_) => DataType::DateTime,
Value::Instant(_) => DataType::Instant,
Value::BigInteger(_) => DataType::BigInteger,
Value::BigDecimal(_) => DataType::BigDecimal,
Value::IntSize(_) => DataType::IntSize,
Value::UIntSize(_) => DataType::UIntSize,
Value::Duration(_) => DataType::Duration,
Value::Url(_) => DataType::Url,
Value::StringMap(_) => DataType::StringMap,
Value::Json(_) => DataType::Json,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
matches!(self, Value::Empty(_))
}
#[inline]
pub fn clear(&mut self) {
let dt = self.data_type();
*self = Value::Empty(dt);
}
#[inline]
pub fn set_type(&mut self, data_type: DataType) {
if self.data_type() != data_type {
*self = Value::Empty(data_type);
}
}
}
impl Default for Value {
#[inline]
fn default() -> Self {
Value::Empty(DataType::String)
}
}