use std::borrow::Cow;
use std::collections::HashMap;
use std::time::Duration;
#[cfg(feature = "big-decimal")]
use bigdecimal::BigDecimal;
#[cfg(feature = "chrono")]
use chrono::{
DateTime,
NaiveDate,
NaiveDateTime,
NaiveTime,
Utc,
};
#[cfg(feature = "big-integer")]
use num_bigint::BigInt;
#[cfg(feature = "url")]
use url::Url;
use super::data_conversion_target::DataConversionTarget;
use super::error::{
DataConversionError,
InvalidValueReason,
};
use super::options::DataConversionOptions;
use crate::datatype::{
DataType,
for_each_data_type_mapping,
};
mod boolean;
mod duration;
mod internal;
mod numeric;
mod source;
mod string_source;
mod structured;
mod text;
macro_rules! data_converter_data_type_match {
($value:expr; $( $(#[$meta:meta])* ($variant:ident, $source:ty, $strategy:ident) ),+ $(,)?) => {
match $value {
Self::Unset(data_type) => *data_type,
$(
$(#[$meta])*
Self::$variant(_) => DataType::$variant,
)+
}
};
}
#[must_use]
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum DataConverter<'a> {
Unset(
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,
),
Float32(
f32,
),
Float64(
f64,
),
#[cfg(feature = "big-integer")]
BigInteger(
Cow<'a, BigInt>,
),
#[cfg(feature = "big-decimal")]
BigDecimal(
Cow<'a, BigDecimal>,
),
String(
Cow<'a, str>,
),
#[cfg(feature = "chrono")]
Date(
NaiveDate,
),
#[cfg(feature = "chrono")]
Time(
NaiveTime,
),
#[cfg(feature = "chrono")]
DateTime(
NaiveDateTime,
),
#[cfg(feature = "chrono")]
Instant(
DateTime<Utc>,
),
Duration(
Duration,
),
#[cfg(feature = "url")]
Url(
Cow<'a, Url>,
),
StringMap(
Cow<'a, HashMap<String, String>>,
),
#[cfg(feature = "json")]
Json(
Cow<'a, serde_json::Value>,
),
}
impl DataConverter<'_> {
#[inline(always)]
pub fn to<T>(&self) -> Result<T, DataConversionError>
where
T: DataConversionTarget,
{
self.to_with(DataConversionOptions::default_ref())
}
#[inline(always)]
pub fn to_with<T>(
&self,
options: &DataConversionOptions,
) -> Result<T, DataConversionError>
where
T: DataConversionTarget,
{
T::convert_from(self, options)
}
#[inline(always)]
pub fn into_target<T>(self) -> Result<T, DataConversionError>
where
T: DataConversionTarget,
{
self.into_target_with(DataConversionOptions::default_ref())
}
#[inline(always)]
pub fn into_target_with<T>(
self,
options: &DataConversionOptions,
) -> Result<T, DataConversionError>
where
T: DataConversionTarget,
{
T::convert_owned(self, options)
}
#[inline(always)]
pub const fn data_type(&self) -> DataType {
for_each_data_type_mapping!(data_converter_data_type_match, self)
}
#[inline(always)]
fn missing(&self, to: DataType) -> DataConversionError {
DataConversionError::missing(self.data_type(), to)
}
#[inline(always)]
fn unsupported(&self, to: DataType) -> DataConversionError {
DataConversionError::unsupported(self.data_type(), to)
}
#[inline(always)]
fn invalid(
&self,
to: DataType,
reason: InvalidValueReason,
) -> DataConversionError {
DataConversionError::invalid(self.data_type(), to, reason)
}
}