use bigdecimal::BigDecimal;
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
use num_bigint::BigInt;
use num_traits::ToPrimitive;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::Duration;
use url::Url;
use qubit_common::lang::argument::NumericArgument;
use qubit_common::lang::DataType;
use super::error::{ValueError, ValueResult};
#[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),
}
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(_) => 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 {
Value::$variant(v) => {
let conv_fn: fn(&_) -> $ret_type = $conversion;
Ok(conv_fn(v))
},
Value::Empty(_) => Err(ValueError::NoValue),
_ => 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 {
#[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 to<T>(&self) -> ValueResult<T>
where
Self: ValueConverter<T>,
{
<Self as ValueConverter<T>>::convert(self)
}
#[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_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()
}
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,
}),
}
}
}
impl Default for Value {
#[inline]
fn default() -> Self {
Value::Empty(DataType::String)
}
}
fn parse_duration_string(s: &str) -> ValueResult<Duration> {
let trimmed = s.trim();
let nanos_text = trimmed.strip_suffix("ns").ok_or_else(|| {
ValueError::ConversionError(format!(
"Cannot convert '{}' to Duration: expected '<nanoseconds>ns'",
s
))
})?;
let total_nanos = nanos_text.parse::<u128>().map_err(|_| {
ValueError::ConversionError(format!(
"Cannot convert '{}' to Duration: invalid nanoseconds value",
s
))
})?;
let secs = total_nanos / 1_000_000_000;
if secs > u64::MAX as u128 {
return Err(ValueError::ConversionError(format!(
"Cannot convert '{}' to Duration: value out of range",
s
)));
}
let nanos = (total_nanos % 1_000_000_000) as u32;
Ok(Duration::new(secs as u64, nanos))
}
fn range_check<T>(value: T, min: T, max: T, target: &str) -> ValueResult<T>
where
T: NumericArgument + Copy,
{
value
.require_in_closed_range("value", min, max)
.map_err(|e| {
ValueError::ConversionError(format!("Cannot convert value to {}: {}", target, e))
})
}
#[doc(hidden)]
pub trait ValueGetter<T> {
fn get_value(&self) -> ValueResult<T>;
}
#[doc(hidden)]
pub trait ValueConstructor<T> {
fn from_type(value: T) -> Self;
}
#[doc(hidden)]
pub trait ValueSetter<T> {
fn set_value(&mut self, value: T) -> ValueResult<()>;
}
#[doc(hidden)]
pub trait ValueConverter<T> {
fn convert(&self) -> ValueResult<T>;
}
macro_rules! impl_value_traits {
($type:ty, $variant:ident, $get_method:ident, $set_method:ident) => {
impl ValueGetter<$type> for Value {
#[inline]
fn get_value(&self) -> ValueResult<$type> {
self.$get_method()
}
}
impl ValueSetter<$type> for Value {
#[inline]
fn set_value(&mut self, value: $type) -> ValueResult<()> {
self.$set_method(value)
}
}
impl ValueConstructor<$type> for Value {
#[inline]
fn from_type(value: $type) -> Self {
Value::$variant(value)
}
}
};
}
macro_rules! impl_strict_value_converter {
($(#[$attr:meta])* $type:ty, $get_method:ident) => {
$(#[$attr])*
impl ValueConverter<$type> for Value {
#[inline]
fn convert(&self) -> ValueResult<$type> {
self.$get_method()
}
}
};
}
impl_value_traits!(bool, Bool, get_bool, set_bool);
impl_value_traits!(char, Char, get_char, set_char);
impl_value_traits!(i8, Int8, get_int8, set_int8);
impl_value_traits!(i16, Int16, get_int16, set_int16);
impl_value_traits!(i32, Int32, get_int32, set_int32);
impl_value_traits!(i64, Int64, get_int64, set_int64);
impl_value_traits!(i128, Int128, get_int128, set_int128);
impl_value_traits!(u8, UInt8, get_uint8, set_uint8);
impl_value_traits!(u16, UInt16, get_uint16, set_uint16);
impl_value_traits!(u32, UInt32, get_uint32, set_uint32);
impl_value_traits!(u64, UInt64, get_uint64, set_uint64);
impl_value_traits!(u128, UInt128, get_uint128, set_uint128);
impl_value_traits!(f32, Float32, get_float32, set_float32);
impl_value_traits!(f64, Float64, get_float64, set_float64);
impl_value_traits!(NaiveDate, Date, get_date, set_date);
impl_value_traits!(NaiveTime, Time, get_time, set_time);
impl_value_traits!(NaiveDateTime, DateTime, get_datetime, set_datetime);
impl_value_traits!(DateTime<Utc>, Instant, get_instant, set_instant);
impl_value_traits!(BigInt, BigInteger, get_biginteger, set_biginteger);
impl_value_traits!(BigDecimal, BigDecimal, get_bigdecimal, set_bigdecimal);
impl_value_traits!(isize, IntSize, get_intsize, set_intsize);
impl_value_traits!(usize, UIntSize, get_uintsize, set_uintsize);
impl_value_traits!(Duration, Duration, get_duration, set_duration);
impl ValueGetter<String> for Value {
#[inline]
fn get_value(&self) -> ValueResult<String> {
self.get_string().map(|s| s.to_string())
}
}
impl ValueSetter<String> for Value {
#[inline]
fn set_value(&mut self, value: String) -> ValueResult<()> {
self.set_string(value)
}
}
impl ValueConstructor<String> for Value {
#[inline]
fn from_type(value: String) -> Self {
Value::String(value)
}
}
impl ValueConverter<String> for Value {
fn convert(&self) -> ValueResult<String> {
match self {
Value::String(v) => Ok(v.clone()),
Value::Bool(v) => Ok(v.to_string()),
Value::Char(v) => Ok(v.to_string()),
Value::Int8(v) => Ok(v.to_string()),
Value::Int16(v) => Ok(v.to_string()),
Value::Int32(v) => Ok(v.to_string()),
Value::Int64(v) => Ok(v.to_string()),
Value::Int128(v) => Ok(v.to_string()),
Value::UInt8(v) => Ok(v.to_string()),
Value::UInt16(v) => Ok(v.to_string()),
Value::UInt32(v) => Ok(v.to_string()),
Value::UInt64(v) => Ok(v.to_string()),
Value::UInt128(v) => Ok(v.to_string()),
Value::Float32(v) => Ok(v.to_string()),
Value::Float64(v) => Ok(v.to_string()),
Value::Date(v) => Ok(v.to_string()),
Value::Time(v) => Ok(v.to_string()),
Value::DateTime(v) => Ok(v.to_string()),
Value::Instant(v) => Ok(v.to_rfc3339()),
Value::BigInteger(v) => Ok(v.to_string()),
Value::BigDecimal(v) => Ok(v.to_string()),
Value::IntSize(v) => Ok(v.to_string()),
Value::UIntSize(v) => Ok(v.to_string()),
Value::Duration(v) => Ok(format!("{}ns", v.as_nanos())),
Value::Url(v) => Ok(v.to_string()),
Value::StringMap(v) => serde_json::to_string(v)
.map_err(|e| ValueError::JsonSerializationError(e.to_string())),
Value::Json(v) => serde_json::to_string(v)
.map_err(|e| ValueError::JsonSerializationError(e.to_string())),
Value::Empty(_) => Err(ValueError::NoValue),
}
}
}
impl ValueSetter<&str> for Value {
#[inline]
fn set_value(&mut self, value: &str) -> ValueResult<()> {
self.set_string(value.to_string())
}
}
impl ValueConstructor<&str> for Value {
#[inline]
fn from_type(value: &str) -> Self {
Value::String(value.to_string())
}
}
impl ValueConverter<bool> for Value {
fn convert(&self) -> ValueResult<bool> {
match self {
Value::Bool(v) => Ok(*v),
Value::Int8(v) => Ok(*v != 0),
Value::Int16(v) => Ok(*v != 0),
Value::Int32(v) => Ok(*v != 0),
Value::Int64(v) => Ok(*v != 0),
Value::Int128(v) => Ok(*v != 0),
Value::UInt8(v) => Ok(*v != 0),
Value::UInt16(v) => Ok(*v != 0),
Value::UInt32(v) => Ok(*v != 0),
Value::UInt64(v) => Ok(*v != 0),
Value::UInt128(v) => Ok(*v != 0),
Value::String(s) => s.parse::<bool>().map_err(|_| {
ValueError::ConversionError(format!("Cannot convert '{}' to boolean", s))
}),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Bool,
}),
}
}
}
impl ValueConverter<i32> for Value {
fn convert(&self) -> ValueResult<i32> {
match self {
Value::Int32(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => Ok(*v as i32),
Value::Int8(v) => Ok(*v as i32),
Value::Int16(v) => Ok(*v as i32),
Value::Int64(v) => (*v)
.try_into()
.map_err(|_| ValueError::ConversionError("i64 value out of i32 range".to_string())),
Value::Int128(v) => (*v).try_into().map_err(|_| {
ValueError::ConversionError("i128 value out of i32 range".to_string())
}),
Value::UInt8(v) => Ok(*v as i32),
Value::UInt16(v) => Ok(*v as i32),
Value::UInt32(v) => (*v)
.try_into()
.map_err(|_| ValueError::ConversionError("u32 value out of i32 range".to_string())),
Value::UInt64(v) => (*v)
.try_into()
.map_err(|_| ValueError::ConversionError("u64 value out of i32 range".to_string())),
Value::UInt128(v) => (*v).try_into().map_err(|_| {
ValueError::ConversionError("u128 value out of i32 range".to_string())
}),
Value::Float32(v) => Ok(*v as i32),
Value::Float64(v) => Ok(*v as i32),
Value::String(s) => s
.parse::<i32>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to i32", s))),
Value::Empty(_) => Err(ValueError::NoValue),
Value::BigInteger(v) => v.to_i32().ok_or_else(|| {
ValueError::ConversionError("BigInteger value out of i32 range".to_string())
}),
Value::BigDecimal(v) => v.to_i32().ok_or_else(|| {
ValueError::ConversionError(
"BigDecimal value cannot be converted to i32".to_string(),
)
}),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Int32,
}),
}
}
}
impl ValueConverter<i64> for Value {
fn convert(&self) -> ValueResult<i64> {
match self {
Value::Int64(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => Ok(*v as i64),
Value::Int8(v) => Ok(*v as i64),
Value::Int16(v) => Ok(*v as i64),
Value::Int32(v) => Ok(*v as i64),
Value::Int128(v) => (*v).try_into().map_err(|_| {
ValueError::ConversionError("i128 value out of i64 range".to_string())
}),
Value::UInt8(v) => Ok(*v as i64),
Value::UInt16(v) => Ok(*v as i64),
Value::UInt32(v) => Ok(*v as i64),
Value::UInt64(v) => (*v)
.try_into()
.map_err(|_| ValueError::ConversionError("u64 value out of i64 range".to_string())),
Value::UInt128(v) => (*v).try_into().map_err(|_| {
ValueError::ConversionError("u128 value out of i64 range".to_string())
}),
Value::Float32(v) => Ok(*v as i64),
Value::Float64(v) => Ok(*v as i64),
Value::String(s) => s
.parse::<i64>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to i64", s))),
Value::Empty(_) => Err(ValueError::NoValue),
Value::BigInteger(v) => v.to_i64().ok_or_else(|| {
ValueError::ConversionError("BigInteger value out of i64 range".to_string())
}),
Value::BigDecimal(v) => v.to_i64().ok_or_else(|| {
ValueError::ConversionError(
"BigDecimal value cannot be converted to i64".to_string(),
)
}),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Int64,
}),
}
}
}
impl ValueConverter<f64> for Value {
fn convert(&self) -> ValueResult<f64> {
match self {
Value::Float64(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1.0 } else { 0.0 }),
Value::Char(v) => Ok(*v as u32 as f64),
Value::Float32(v) => Ok(*v as f64),
Value::Int8(v) => Ok(*v as f64),
Value::Int16(v) => Ok(*v as f64),
Value::Int32(v) => Ok(*v as f64),
Value::Int64(v) => Ok(*v as f64),
Value::Int128(v) => Ok(*v as f64),
Value::UInt8(v) => Ok(*v as f64),
Value::UInt16(v) => Ok(*v as f64),
Value::UInt32(v) => Ok(*v as f64),
Value::UInt64(v) => Ok(*v as f64),
Value::UInt128(v) => Ok(*v as f64),
Value::String(s) => s
.parse::<f64>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to f64", s))),
Value::Empty(_) => Err(ValueError::NoValue),
Value::BigInteger(v) => Ok(v.to_f64().unwrap_or(f64::INFINITY)),
Value::BigDecimal(v) => Ok(v.to_f64().unwrap_or(f64::INFINITY)),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Float64,
}),
}
}
}
impl ValueGetter<Url> for Value {
#[inline]
fn get_value(&self) -> ValueResult<Url> {
self.get_url()
}
}
impl ValueSetter<Url> for Value {
#[inline]
fn set_value(&mut self, value: Url) -> ValueResult<()> {
self.set_url(value)
}
}
impl ValueConstructor<Url> for Value {
#[inline]
fn from_type(value: Url) -> Self {
Value::Url(value)
}
}
impl ValueConverter<Duration> for Value {
fn convert(&self) -> ValueResult<Duration> {
match self {
Value::Duration(v) => Ok(*v),
Value::String(s) => parse_duration_string(s),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Duration,
}),
}
}
}
impl ValueConverter<Url> for Value {
fn convert(&self) -> ValueResult<Url> {
match self {
Value::Url(v) => Ok(v.clone()),
Value::String(s) => Url::parse(s).map_err(|e| {
ValueError::ConversionError(format!("Cannot convert '{}' to Url: {}", s, e))
}),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Url,
}),
}
}
}
impl ValueGetter<HashMap<String, String>> for Value {
#[inline]
fn get_value(&self) -> ValueResult<HashMap<String, String>> {
self.get_string_map()
}
}
impl ValueSetter<HashMap<String, String>> for Value {
#[inline]
fn set_value(&mut self, value: HashMap<String, String>) -> ValueResult<()> {
self.set_string_map(value)
}
}
impl ValueConstructor<HashMap<String, String>> for Value {
#[inline]
fn from_type(value: HashMap<String, String>) -> Self {
Value::StringMap(value)
}
}
impl ValueGetter<serde_json::Value> for Value {
#[inline]
fn get_value(&self) -> ValueResult<serde_json::Value> {
self.get_json()
}
}
impl ValueSetter<serde_json::Value> for Value {
#[inline]
fn set_value(&mut self, value: serde_json::Value) -> ValueResult<()> {
self.set_json(value)
}
}
impl ValueConstructor<serde_json::Value> for Value {
#[inline]
fn from_type(value: serde_json::Value) -> Self {
Value::Json(value)
}
}
impl ValueConverter<serde_json::Value> for Value {
fn convert(&self) -> ValueResult<serde_json::Value> {
match self {
Value::Json(v) => Ok(v.clone()),
Value::String(s) => serde_json::from_str(s)
.map_err(|e| ValueError::JsonDeserializationError(e.to_string())),
Value::StringMap(v) => serde_json::to_value(v)
.map_err(|e| ValueError::JsonSerializationError(e.to_string())),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Json,
}),
}
}
}
impl_strict_value_converter!(
char,
get_char
);
impl_strict_value_converter!(
i8,
get_int8
);
impl_strict_value_converter!(
i16,
get_int16
);
impl_strict_value_converter!(
i128,
get_int128
);
impl ValueConverter<u8> for Value {
fn convert(&self) -> ValueResult<u8> {
match self {
Value::UInt8(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => {
let code = range_check(*v as u32, u8::MIN as u32, u8::MAX as u32, "u8")?;
Ok(code as u8)
}
Value::Int8(v) => {
let n = range_check(*v, 0i8, i8::MAX, "u8")?;
Ok(n as u8)
}
Value::Int16(v) => {
let n = range_check(*v, u8::MIN as i16, u8::MAX as i16, "u8")?;
Ok(n as u8)
}
Value::Int32(v) => {
let n = range_check(*v, u8::MIN as i32, u8::MAX as i32, "u8")?;
Ok(n as u8)
}
Value::Int64(v) => {
let n = range_check(*v, u8::MIN as i64, u8::MAX as i64, "u8")?;
Ok(n as u8)
}
Value::Int128(v) => {
let n = range_check(*v, u8::MIN as i128, u8::MAX as i128, "u8")?;
Ok(n as u8)
}
Value::UInt16(v) => {
let n = range_check(*v, u8::MIN as u16, u8::MAX as u16, "u8")?;
Ok(n as u8)
}
Value::UInt32(v) => {
let n = range_check(*v, u8::MIN as u32, u8::MAX as u32, "u8")?;
Ok(n as u8)
}
Value::UInt64(v) => {
let n = range_check(*v, u8::MIN as u64, u8::MAX as u64, "u8")?;
Ok(n as u8)
}
Value::UInt128(v) => {
let n = range_check(*v, u8::MIN as u128, u8::MAX as u128, "u8")?;
Ok(n as u8)
}
Value::String(s) => s
.parse::<u8>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to u8", s))),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::UInt8,
}),
}
}
}
impl ValueConverter<u16> for Value {
fn convert(&self) -> ValueResult<u16> {
match self {
Value::UInt8(v) => Ok((*v).into()),
Value::UInt16(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => {
let code = range_check(*v as u32, u16::MIN as u32, u16::MAX as u32, "u16")?;
Ok(code as u16)
}
Value::Int8(v) => {
let n = range_check(*v, 0i8, i8::MAX, "u16")?;
Ok(n as u16)
}
Value::Int16(v) => {
let n = range_check(*v, 0i16, i16::MAX, "u16")?;
Ok(n as u16)
}
Value::Int32(v) => {
let n = range_check(*v, u16::MIN as i32, u16::MAX as i32, "u16")?;
Ok(n as u16)
}
Value::Int64(v) => {
let n = range_check(*v, u16::MIN as i64, u16::MAX as i64, "u16")?;
Ok(n as u16)
}
Value::Int128(v) => {
let n = range_check(*v, u16::MIN as i128, u16::MAX as i128, "u16")?;
Ok(n as u16)
}
Value::UInt32(v) => {
let n = range_check(*v, u16::MIN as u32, u16::MAX as u32, "u16")?;
Ok(n as u16)
}
Value::UInt64(v) => {
let n = range_check(*v, u16::MIN as u64, u16::MAX as u64, "u16")?;
Ok(n as u16)
}
Value::UInt128(v) => {
let n = range_check(*v, u16::MIN as u128, u16::MAX as u128, "u16")?;
Ok(n as u16)
}
Value::String(s) => s
.parse::<u16>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to u16", s))),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::UInt16,
}),
}
}
}
impl ValueConverter<u32> for Value {
fn convert(&self) -> ValueResult<u32> {
match self {
Value::UInt8(v) => Ok((*v).into()),
Value::UInt16(v) => Ok((*v).into()),
Value::UInt32(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => Ok(*v as u32),
Value::Int8(v) => {
let n = range_check(*v, 0i8, i8::MAX, "u32")?;
Ok(n as u32)
}
Value::Int16(v) => {
let n = range_check(*v, 0i16, i16::MAX, "u32")?;
Ok(n as u32)
}
Value::Int32(v) => {
let n = range_check(*v, 0i32, i32::MAX, "u32")?;
Ok(n as u32)
}
Value::Int64(v) => {
let n = range_check(*v, u32::MIN as i64, u32::MAX as i64, "u32")?;
Ok(n as u32)
}
Value::Int128(v) => {
let n = range_check(*v, u32::MIN as i128, u32::MAX as i128, "u32")?;
Ok(n as u32)
}
Value::UInt64(v) => {
let n = range_check(*v, u32::MIN as u64, u32::MAX as u64, "u32")?;
Ok(n as u32)
}
Value::UInt128(v) => {
let n = range_check(*v, u32::MIN as u128, u32::MAX as u128, "u32")?;
Ok(n as u32)
}
Value::String(s) => s
.parse::<u32>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to u32", s))),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::UInt32,
}),
}
}
}
impl ValueConverter<u64> for Value {
fn convert(&self) -> ValueResult<u64> {
match self {
Value::UInt8(v) => Ok((*v).into()),
Value::UInt16(v) => Ok((*v).into()),
Value::UInt32(v) => Ok((*v).into()),
Value::UInt64(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => Ok((*v as u32).into()),
Value::Int8(v) => {
let n = range_check(*v, 0i8, i8::MAX, "u64")?;
Ok(n as u64)
}
Value::Int16(v) => {
let n = range_check(*v, 0i16, i16::MAX, "u64")?;
Ok(n as u64)
}
Value::Int32(v) => {
let n = range_check(*v, 0i32, i32::MAX, "u64")?;
Ok(n as u64)
}
Value::Int64(v) => {
let n = range_check(*v, 0i64, i64::MAX, "u64")?;
Ok(n as u64)
}
Value::Int128(v) => {
let n = range_check(*v, 0i128, u64::MAX as i128, "u64")?;
Ok(n as u64)
}
Value::UInt128(v) => {
let n = range_check(*v, u64::MIN as u128, u64::MAX as u128, "u64")?;
Ok(n as u64)
}
Value::String(s) => s
.parse::<u64>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to u64", s))),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::UInt64,
}),
}
}
}
impl ValueConverter<u128> for Value {
fn convert(&self) -> ValueResult<u128> {
match self {
Value::UInt8(v) => Ok((*v).into()),
Value::UInt16(v) => Ok((*v).into()),
Value::UInt32(v) => Ok((*v).into()),
Value::UInt64(v) => Ok((*v).into()),
Value::UInt128(v) => Ok(*v),
Value::Bool(v) => Ok(if *v { 1 } else { 0 }),
Value::Char(v) => Ok((*v as u32).into()),
Value::Int8(v) => {
let n = range_check(*v, 0i8, i8::MAX, "u128")?;
Ok(n as u128)
}
Value::Int16(v) => {
let n = range_check(*v, 0i16, i16::MAX, "u128")?;
Ok(n as u128)
}
Value::Int32(v) => {
let n = range_check(*v, 0i32, i32::MAX, "u128")?;
Ok(n as u128)
}
Value::Int64(v) => {
let n = range_check(*v, 0i64, i64::MAX, "u128")?;
Ok(n as u128)
}
Value::Int128(v) => {
let n = range_check(*v, 0i128, i128::MAX, "u128")?;
Ok(n as u128)
}
Value::String(s) => s.parse::<u128>().map_err(|_| {
ValueError::ConversionError(format!("Cannot convert '{}' to u128", s))
}),
Value::Empty(_) => Err(ValueError::NoValue),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::UInt128,
}),
}
}
}
impl ValueConverter<f32> for Value {
fn convert(&self) -> ValueResult<f32> {
match self {
Value::Float32(v) => Ok(*v),
Value::Float64(v) => {
if v.is_nan() || v.is_infinite() {
Ok(*v as f32)
} else {
let n = range_check(*v, f32::MIN as f64, f32::MAX as f64, "f32")?;
Ok(n as f32)
}
}
Value::Bool(v) => Ok(if *v { 1.0 } else { 0.0 }),
Value::Char(v) => Ok(*v as u32 as f32),
Value::Int8(v) => Ok(*v as f32),
Value::Int16(v) => Ok(*v as f32),
Value::Int32(v) => Ok(*v as f32),
Value::Int64(v) => Ok(*v as f32),
Value::Int128(v) => Ok(*v as f32),
Value::UInt8(v) => Ok(*v as f32),
Value::UInt16(v) => Ok(*v as f32),
Value::UInt32(v) => Ok(*v as f32),
Value::UInt64(v) => Ok(*v as f32),
Value::UInt128(v) => Ok(*v as f32),
Value::String(s) => s
.parse::<f32>()
.map_err(|_| ValueError::ConversionError(format!("Cannot convert '{}' to f32", s))),
Value::Empty(_) => Err(ValueError::NoValue),
Value::BigInteger(v) => Ok(v.to_f32().unwrap_or(f32::INFINITY)),
Value::BigDecimal(v) => Ok(v.to_f32().unwrap_or(f32::INFINITY)),
_ => Err(ValueError::ConversionFailed {
from: self.data_type(),
to: DataType::Float32,
}),
}
}
}
impl_strict_value_converter!(
NaiveDate,
get_date
);
impl_strict_value_converter!(
NaiveTime,
get_time
);
impl_strict_value_converter!(
NaiveDateTime,
get_datetime
);
impl_strict_value_converter!(
DateTime<Utc>,
get_instant
);
impl_strict_value_converter!(
BigInt,
get_biginteger
);
impl_strict_value_converter!(
BigDecimal,
get_bigdecimal
);
impl_strict_value_converter!(
isize,
get_intsize
);
impl_strict_value_converter!(
usize,
get_uintsize
);
impl_strict_value_converter!(
HashMap<String, String>,
get_string_map
);