use qubit_datatype::{
DataConversionError,
DataConversionOptions,
DataConvertTo,
DataConverter,
DataConverters,
DataListConversionError,
DataType,
ScalarStringDataConverters,
};
use crate::value_error::{
ValueError,
ValueResult,
};
use crate::{
IntoValueDefault,
Value,
};
use super::multi_values::MultiValues;
macro_rules! multi_values_to_value_match {
($value:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
match $value {
MultiValues::Empty(data_type) => Value::Empty(*data_type),
$(
MultiValues::$variant(values) => values
.first()
.cloned()
.map(Value::$variant)
.unwrap_or(Value::Empty($data_type)),
)+
}
};
}
macro_rules! multi_values_merge_match {
($left:expr, $right:expr; $(($variant:ident, $type:ty, $data_type:expr)),+ $(,)?) => {
match ($left, $right) {
$(
(MultiValues::$variant(values), MultiValues::$variant(other_values)) => {
values.extend_from_slice(other_values)
}
)+
(slot @ MultiValues::Empty(_), other_values) => *slot = other_values.clone(),
_ => unreachable!(),
}
};
}
fn map_data_conversion_error(error: DataConversionError) -> ValueError {
match error {
DataConversionError::NoValue => ValueError::NoValue,
DataConversionError::ConversionFailed { from, to } => {
ValueError::ConversionFailed { from, to }
}
DataConversionError::ConversionError(message) => ValueError::ConversionError(message),
DataConversionError::JsonSerializationError(message) => {
ValueError::JsonSerializationError(message)
}
DataConversionError::JsonDeserializationError(message) => {
ValueError::JsonDeserializationError(message)
}
}
}
#[inline]
fn map_data_list_conversion_error(error: DataListConversionError) -> ValueError {
let source = map_data_conversion_error(error.source);
ValueError::ConversionError(format!(
"Cannot convert value at index {}: {}",
error.index, source
))
}
#[inline]
fn convert_first_with<'a, T, I>(
values: DataConverters<'a, I>,
options: &DataConversionOptions,
) -> ValueResult<T>
where
DataConverter<'a>: DataConvertTo<T>,
I: Iterator,
I::Item: Into<DataConverter<'a>>,
{
values
.to_first_with(options)
.map_err(map_data_conversion_error)
}
#[inline]
fn convert_values_with<'a, T, I>(
values: DataConverters<'a, I>,
options: &DataConversionOptions,
) -> ValueResult<Vec<T>>
where
DataConverter<'a>: DataConvertTo<T>,
I: Iterator,
I::Item: Into<DataConverter<'a>>,
{
values
.to_vec_with(options)
.map_err(map_data_list_conversion_error)
}
impl MultiValues {
#[inline]
pub fn to<T>(&self) -> ValueResult<T>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
self.to_with(&DataConversionOptions::default())
}
#[inline]
pub fn to_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
where
for<'a> DataConverter<'a>: DataConvertTo<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>,
{
match self {
MultiValues::Empty(_) => Err(ValueError::NoValue),
MultiValues::Bool(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Char(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Int8(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Int16(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Int32(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Int64(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Int128(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::UInt8(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::UInt16(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::UInt32(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::UInt64(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::UInt128(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::IntSize(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::UIntSize(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Float32(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Float64(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::BigInteger(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::BigDecimal(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::String(v) if v.len() == 1 => {
ScalarStringDataConverters::from(v[0].as_str())
.to_first_with(options)
.map_err(map_data_conversion_error)
}
MultiValues::String(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Date(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Time(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::DateTime(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Instant(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Duration(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Url(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::StringMap(v) => convert_first_with(DataConverters::from(v), options),
MultiValues::Json(v) => convert_first_with(DataConverters::from(v), 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,
}
}
pub fn to_list<T>(&self) -> ValueResult<Vec<T>>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
self.to_list_with(&DataConversionOptions::default())
}
#[inline]
pub fn to_list_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
let values = self.to_list()?;
if values.is_empty() {
Ok(default.into_value_default())
} else {
Ok(values)
}
}
pub fn to_list_with<T>(&self, options: &DataConversionOptions) -> ValueResult<Vec<T>>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
match self {
MultiValues::Empty(_) => Ok(Vec::new()),
MultiValues::Bool(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Char(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Int8(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Int16(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Int32(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Int64(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Int128(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::UInt8(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::UInt16(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::UInt32(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::UInt64(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::UInt128(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::IntSize(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::UIntSize(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Float32(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Float64(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::BigInteger(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::BigDecimal(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::String(v) if v.len() == 1 => {
ScalarStringDataConverters::from(v[0].as_str())
.to_vec_with(options)
.map_err(map_data_list_conversion_error)
}
MultiValues::String(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Date(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Time(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::DateTime(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Instant(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Duration(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Url(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::StringMap(v) => convert_values_with(DataConverters::from(v), options),
MultiValues::Json(v) => convert_values_with(DataConverters::from(v), options),
}
}
#[inline]
pub fn to_list_or_with<T>(
&self,
default: impl IntoValueDefault<Vec<T>>,
options: &DataConversionOptions,
) -> ValueResult<Vec<T>>
where
for<'a> DataConverter<'a>: DataConvertTo<T>,
{
let values = self.to_list_with(options)?;
if values.is_empty() {
Ok(default.into_value_default())
} else {
Ok(values)
}
}
pub fn to_value(&self) -> Value {
for_each_multi_value_type!(multi_values_to_value_match, self)
}
pub fn merge(&mut self, other: &MultiValues) -> ValueResult<()> {
if self.data_type() != other.data_type() {
return Err(ValueError::TypeMismatch {
expected: self.data_type(),
actual: other.data_type(),
});
}
if other.count() == 0 {
return Ok(());
}
for_each_multi_value_type!(multi_values_merge_match, self, other);
Ok(())
}
}
impl Default for MultiValues {
#[inline]
fn default() -> Self {
MultiValues::Empty(DataType::String)
}
}
impl From<Value> for MultiValues {
fn from(value: Value) -> Self {
match value {
Value::Empty(dt) => MultiValues::Empty(dt),
Value::Bool(v) => MultiValues::Bool(vec![v]),
Value::Char(v) => MultiValues::Char(vec![v]),
Value::Int8(v) => MultiValues::Int8(vec![v]),
Value::Int16(v) => MultiValues::Int16(vec![v]),
Value::Int32(v) => MultiValues::Int32(vec![v]),
Value::Int64(v) => MultiValues::Int64(vec![v]),
Value::Int128(v) => MultiValues::Int128(vec![v]),
Value::UInt8(v) => MultiValues::UInt8(vec![v]),
Value::UInt16(v) => MultiValues::UInt16(vec![v]),
Value::UInt32(v) => MultiValues::UInt32(vec![v]),
Value::UInt64(v) => MultiValues::UInt64(vec![v]),
Value::UInt128(v) => MultiValues::UInt128(vec![v]),
Value::Float32(v) => MultiValues::Float32(vec![v]),
Value::Float64(v) => MultiValues::Float64(vec![v]),
Value::String(v) => MultiValues::String(vec![v]),
Value::Date(v) => MultiValues::Date(vec![v]),
Value::Time(v) => MultiValues::Time(vec![v]),
Value::DateTime(v) => MultiValues::DateTime(vec![v]),
Value::Instant(v) => MultiValues::Instant(vec![v]),
Value::BigInteger(v) => MultiValues::BigInteger(vec![v]),
Value::BigDecimal(v) => MultiValues::BigDecimal(vec![v]),
Value::IntSize(v) => MultiValues::IntSize(vec![v]),
Value::UIntSize(v) => MultiValues::UIntSize(vec![v]),
Value::Duration(v) => MultiValues::Duration(vec![v]),
Value::Url(v) => MultiValues::Url(vec![v]),
Value::StringMap(v) => MultiValues::StringMap(vec![v]),
Value::Json(v) => MultiValues::Json(vec![v]),
}
}
}