use std::collections::HashMap;
use std::fmt;
#[cfg(feature = "json")]
use std::hash::Hash;
#[cfg(feature = "json")]
use std::hash::Hasher;
use std::time::Duration;
#[cfg(feature = "big-decimal")]
use bigdecimal::BigDecimal;
#[cfg(feature = "chrono")]
use chrono::DateTime;
#[cfg(feature = "chrono")]
use chrono::NaiveDate;
#[cfg(feature = "chrono")]
use chrono::NaiveDateTime;
#[cfg(feature = "chrono")]
use chrono::NaiveTime;
#[cfg(feature = "chrono")]
use chrono::Utc;
#[cfg(feature = "big-integer")]
use num_bigint::BigInt;
#[cfg(feature = "json")]
use qubit_budget::MeasuredBudgetError;
#[cfg(feature = "json")]
use qubit_budget::ResourceQuantity;
#[cfg(feature = "json")]
use qubit_budget::json::JsonValueBudget;
#[cfg(feature = "converter")]
use qubit_datatype::ConversionLimits;
#[cfg(feature = "converter")]
use qubit_datatype::ConversionPolicy;
#[cfg(feature = "converter")]
use qubit_datatype::ConversionSession;
#[cfg(feature = "converter")]
use qubit_datatype::DataConversionError;
#[cfg(feature = "converter")]
use qubit_datatype::DataConversionTarget;
#[cfg(feature = "converter")]
use qubit_datatype::DataConverter;
#[cfg(feature = "converter")]
use qubit_datatype::DataConverters;
use qubit_datatype::DataType;
#[cfg(feature = "url")]
use url::Url;
use super::internal::MultiValuesRepr;
#[cfg(feature = "json")]
use super::multi_values_identity::hash_multi_values_payload_with_json_budget;
use super::multi_values_ref::MultiValuesRef;
use crate::IntoValueDefault;
use crate::Value;
use crate::ValueError;
use crate::ValueResult;
#[cfg(feature = "json")]
use crate::identity::hash_json;
#[cfg(feature = "json")]
use crate::identity::preflight_json;
use crate::value::ValueRepr;
#[must_use]
#[derive(Clone)]
pub struct MultiValues {
pub(crate) repr: MultiValuesRepr,
}
impl fmt::Debug for MultiValues {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.view().fmt(formatter)
}
}
macro_rules! impl_multi_values_constructors {
(
;
$(
(
[$($cfg:meta),*],
$variant:ident,
$type:ty,
$data_type:expr,
$materialization:ident,
$json_class:ident,
$number_projection:ident,
$value_doc:literal,
$multi_doc:literal
$(, $_wire:tt)*
)
),+ $(,)?
) => {
impl MultiValues {
#[allow(non_snake_case)]
#[inline(always)]
pub const fn Unset(data_type: DataType) -> Self {
Self::new_unset(data_type)
}
#[inline(always)]
pub const fn new_unset(data_type: DataType) -> Self {
Self { repr: MultiValuesRepr::Unset(data_type) }
}
$(
#[doc = concat!("Creates a collection of ", $multi_doc, ".")]
$(#[$cfg])*
#[allow(non_snake_case)]
#[inline(always)]
pub fn $variant(values: Vec<$type>) -> Self {
Self { repr: MultiValuesRepr::$variant(values) }
}
)+
}
};
}
macro_rules! owned_view_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(data_type) => MultiValuesRef::Unset(*data_type),
$($(#[$cfg])* MultiValuesRepr::$variant(value) => MultiValuesRef::$variant(
value.as_slice()
),)+
}
};
}
for_each_value_type!(impl_multi_values_constructors);
impl MultiValues {
#[must_use = "the borrowed first-value result should be handled"]
#[inline(always)]
pub fn get_first_ref<'a, T: ?Sized>(&'a self) -> ValueResult<&'a T>
where
&'a T: TryFrom<&'a Self, Error = ValueError>,
{
<&'a T>::try_from(self)
}
#[must_use = "the borrowed collection result should be handled"]
#[inline(always)]
pub fn get_slice<'a, T>(&'a self) -> ValueResult<&'a [T]>
where
&'a [T]: TryFrom<&'a Self, Error = ValueError>,
{
<&'a [T]>::try_from(self)
}
#[cfg(feature = "json")]
pub fn hash_with_json_budget<H, R, Q>(
&self,
state: &mut H,
budget: &mut JsonValueBudget<R, Q>,
) -> Result<(), MeasuredBudgetError<R, Q>>
where
H: Hasher,
R: Clone,
Q: ResourceQuantity,
{
match &self.repr {
MultiValuesRepr::Json(values) => {
let mut transaction = budget.transaction();
for value in values {
preflight_json(value, &mut transaction)?;
}
std::mem::discriminant(&self.repr).hash(state);
values.len().hash(state);
for value in values {
hash_json(value, state);
}
transaction.commit()
}
_ => {
std::mem::discriminant(&self.repr).hash(state);
hash_multi_values_payload_with_json_budget(&self.repr, state, budget)
}
}
}
#[must_use = "the borrowed collection view should be used"]
#[inline(always)]
pub fn view(&self) -> MultiValuesRef<'_> {
for_each_value_type!(owned_view_match, self)
}
}
macro_rules! impl_get_multi_values {
($(#[$attr:meta])* slice: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[doc = ""]
#[doc = "# Errors"]
#[doc = ""]
#[doc = "Returns [`ValueError::Missing`] when the container is unset"]
#[doc = "with the requested type, or [`ValueError::TypeMismatch`] when"]
#[doc = "the stored data type differs. A concrete empty vector returns"]
#[doc = "an empty slice."]
#[must_use = "the strict collection read result should be handled"]
#[inline(always)]
pub fn $method(&self) -> ValueResult<&[$type]> {
match &self.repr {
MultiValuesRepr::$variant(v) => Ok(v),
MultiValuesRepr::Unset(dt) if *dt == $data_type => {
Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
}
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
($(#[$attr:meta])* vec: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[doc = ""]
#[doc = "# Errors"]
#[doc = ""]
#[doc = "Returns [`ValueError::Missing`] when the container is unset"]
#[doc = "with the requested type, or [`ValueError::TypeMismatch`] when"]
#[doc = "the stored data type differs. A concrete empty vector returns"]
#[doc = "an empty slice."]
#[must_use = "the strict collection read result should be handled"]
#[inline(always)]
pub fn $method(&self) -> ValueResult<&[$type]> {
match &self.repr {
MultiValuesRepr::$variant(v) => Ok(v.as_slice()),
MultiValuesRepr::Unset(dt) if *dt == $data_type => {
Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
}
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
macro_rules! impl_get_first_value {
($(#[$attr:meta])* copy: $method:ident, $variant:ident, $type:ty, $data_type:expr) => {
$(#[$attr])*
#[doc = ""]
#[doc = "# Errors"]
#[doc = ""]
#[doc = "Returns [`ValueError::Missing`] when the requested type matches"]
#[doc = "but no value is stored, or [`ValueError::TypeMismatch`] when"]
#[doc = "the stored data type differs."]
#[must_use = "the strict first-value result should be handled"]
#[inline(always)]
pub fn $method(&self) -> ValueResult<$type> {
match &self.repr {
MultiValuesRepr::$variant(v) if !v.is_empty() => Ok(v[0]),
MultiValuesRepr::$variant(_) => {
Err(ValueError::Missing($crate::ValueMissing::empty_collection($data_type, $data_type)))
}
MultiValuesRepr::Unset(dt) if *dt == $data_type => {
Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *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])*
#[doc = ""]
#[doc = "# Errors"]
#[doc = ""]
#[doc = "Returns [`ValueError::Missing`] when the requested type matches"]
#[doc = "but no value is stored, or [`ValueError::TypeMismatch`] when"]
#[doc = "the stored data type differs."]
#[must_use = "the strict first-value result should be handled"]
#[inline(always)]
pub fn $method(&self) -> ValueResult<$ret_type> {
match &self.repr {
MultiValuesRepr::$variant(v) if !v.is_empty() => {
let conv_fn: fn(&_) -> $ret_type = $conversion;
Ok(conv_fn(&v[0]))
},
MultiValuesRepr::$variant(_) => {
Err(ValueError::Missing($crate::ValueMissing::empty_collection($data_type, $data_type)))
}
MultiValuesRepr::Unset(dt) if *dt == $data_type => {
Err(ValueError::Missing($crate::ValueMissing::unset_collection(*dt, *dt)))
}
_ => Err(ValueError::TypeMismatch {
expected: $data_type,
actual: self.data_type(),
}),
}
}
};
}
#[cfg(all(feature = "converter", feature = "json"))]
impl MultiValues {
#[inline(always)]
pub fn to_json_value(&self) -> ValueResult<serde_json::Value> {
self.to_json_value_with(ConversionPolicy::default_ref(), ConversionLimits::default_ref())
}
#[inline(always)]
pub fn to_json_value_with(
&self,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<serde_json::Value> {
crate::json::multi_values_to_json_value_with(self, policy, limits)
}
}
macro_rules! multi_values_data_type_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(dt) => *dt,
$($(#[$cfg])* MultiValuesRepr::$variant(_) => $data_type,)+
}
};
}
macro_rules! multi_values_count_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(_) => 0,
$($(#[$cfg])* MultiValuesRepr::$variant(values) => values.len(),)+
}
};
}
macro_rules! multi_values_clear_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &mut $value.repr {
MultiValuesRepr::Unset(_) => {}
$($(#[$cfg])* MultiValuesRepr::$variant(values) => values.clear(),)+
}
};
}
macro_rules! multi_values_append_match {
($left:expr, $right:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match (&mut $left.repr, &mut $right.repr) {
$(
$(#[$cfg])*
(MultiValuesRepr::$variant(values), MultiValuesRepr::$variant(other_values)) => {
values.append(other_values);
}
)+
(slot @ MultiValuesRepr::Unset(_), other_values) => {
*slot = std::mem::replace(other_values, MultiValuesRepr::Unset(DataType::String));
}
_ => unreachable!(),
}
};
}
macro_rules! multi_values_first_value_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(data_type) => Value::new_unset(*data_type),
$(
$(#[$cfg])*
MultiValuesRepr::$variant(values) => values
.first()
.map(|value| materialize_stored!($materialization, value))
.map(Value::$variant)
.unwrap_or(Value::new_unset($data_type)),
)+
}
};
}
macro_rules! multi_values_into_first_value_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match $value.repr {
MultiValuesRepr::Unset(data_type) => Value::new_unset(data_type),
$(
$(#[$cfg])*
MultiValuesRepr::$variant(values) => values
.into_iter()
.next()
.map(Value::$variant)
.unwrap_or(Value::new_unset($data_type)),
)+
}
};
}
macro_rules! multi_values_merge_match {
($left:expr, $right:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match (&mut $left.repr, &$right.repr) {
$(
$(#[$cfg])*
(MultiValuesRepr::$variant(values), MultiValuesRepr::$variant(other_values)) => {
values.extend_from_slice(other_values)
}
)+
(slot @ MultiValuesRepr::Unset(_), other_values) => *slot = other_values.clone(),
_ => unreachable!(),
}
};
}
macro_rules! value_into_multi_values_match {
($value:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match $value.repr {
ValueRepr::Unset(data_type) => MultiValues::new_unset(data_type),
$($(#[$cfg])* ValueRepr::$variant(value) => {
MultiValues::$variant(vec![value_storage_into_multi!($variant, value)])
},)+
}
};
}
impl MultiValues {
#[inline(always)]
pub fn new<S>(values: S) -> Self
where
S: Into<Self>,
{
values.into()
}
#[must_use = "the strict collection read result should be handled"]
#[inline(always)]
pub fn get<T>(&self) -> ValueResult<Vec<T>>
where
for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
{
Vec::<T>::try_from(self)
}
#[must_use = "the strict collection read result should be handled"]
#[inline(always)]
pub fn get_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
where
for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
{
match self.get() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => {
Ok(default.into_value_default())
}
result => result,
}
}
#[must_use = "the strict collection read result should be handled"]
#[inline(always)]
pub fn get_or_else<T, F>(&self, default: F) -> ValueResult<Vec<T>>
where
for<'a> Vec<T>: TryFrom<&'a Self, Error = ValueError>,
F: FnOnce() -> Vec<T>,
{
match self.get() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => Ok(default()),
result => result,
}
}
#[must_use = "the strict first-value result should be handled"]
#[inline(always)]
pub fn get_first<T>(&self) -> ValueResult<T>
where
for<'a> T: TryFrom<&'a Self, Error = ValueError>,
{
T::try_from(self)
}
#[must_use = "the strict first-value result should be handled"]
#[inline(always)]
pub fn get_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
where
for<'a> T: TryFrom<&'a Self, Error = ValueError>,
{
match self.get_first() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => {
Ok(default.into_value_default())
}
result => result,
}
}
#[must_use = "the strict first-value result should be handled"]
#[inline(always)]
pub fn get_first_or_else<T, F>(&self, default: F) -> ValueResult<T>
where
for<'a> T: TryFrom<&'a Self, Error = ValueError>,
F: FnOnce() -> T,
{
match self.get_first() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_strict_read() => Ok(default()),
result => result,
}
}
#[inline(always)]
pub fn set<S>(&mut self, values: S)
where
S: Into<Self>,
{
*self = values.into();
}
pub fn add<S>(&mut self, values: S) -> ValueResult<()>
where
S: Into<Self>,
{
let mut other = values.into();
if self.data_type() != other.data_type() {
return Err(ValueError::TypeMismatch {
expected: self.data_type(),
actual: other.data_type(),
});
}
if other.is_empty() {
return Ok(());
}
for_each_value_type!(multi_values_append_match, self, other);
Ok(())
}
#[must_use = "the collection element type should be used"]
#[inline(always)]
pub fn data_type(&self) -> DataType {
for_each_value_type!(multi_values_data_type_match, self)
}
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
for_each_value_type!(multi_values_count_match, self)
}
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline(always)]
#[must_use]
pub fn is_unset(&self) -> bool {
matches!(self.repr, MultiValuesRepr::Unset(_))
}
#[inline(always)]
#[must_use]
pub fn is_numeric(&self) -> bool {
!self.is_unset() && self.data_type().is_numeric()
}
#[inline(always)]
pub fn unset(&mut self) {
*self = MultiValues::new_unset(self.data_type());
}
#[inline(always)]
pub fn clear(&mut self) {
for_each_value_type!(multi_values_clear_match, self)
}
#[inline(always)]
pub fn set_type(&mut self, data_type: DataType) {
if self.data_type() != data_type {
*self = MultiValues::new_unset(data_type);
}
}
#[must_use = "the projected first value should be used"]
#[inline(always)]
pub fn first_value(&self) -> Value {
for_each_value_type!(multi_values_first_value_match, self)
}
pub fn into_first_value(self) -> Value {
for_each_value_type!(multi_values_into_first_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.is_empty() {
return Ok(());
}
for_each_value_type!(multi_values_merge_match, self, other);
Ok(())
}
}
impl From<Value> for MultiValues {
fn from(value: Value) -> Self {
for_each_value_type!(value_into_multi_values_match, value)
}
}
#[cfg(feature = "converter")]
macro_rules! multi_values_convert_first_match {
($value:expr, $policy:expr, $limits:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(from) => {
Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
}
$(
$(#[$cfg])*
MultiValuesRepr::$variant(values) => {
convert_first_with(DataConverters::from(values), $policy, $limits)
}
)+
}
};
}
#[cfg(feature = "converter")]
macro_rules! multi_values_convert_list_match {
($value:expr, $policy:expr, $limits:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(from) => {
Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
}
$(
$(#[$cfg])*
MultiValuesRepr::$variant(values) => {
convert_values_with(DataConverters::from(values), $policy, $limits)
}
)+
}
};
}
#[cfg(feature = "converter")]
macro_rules! multi_values_convert_first_in_match {
($value:expr, $session:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(from) => {
Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
}
$(
$(#[$cfg])*
MultiValuesRepr::$variant(values) => {
DataConverters::from(values)
.to_first_in($session)
.map_err(ValueError::from)
}
)+
}
};
}
#[cfg(feature = "converter")]
macro_rules! multi_values_convert_list_in_match {
($value:expr, $session:expr; $(([$($cfg:meta),*], $variant:ident, $type:ty, $data_type:expr, $materialization:ident, $json_class:ident, $number_projection:ident, $value_doc:literal, $multi_doc:literal $(, $_wire:tt)*)),+ $(,)?) => {
match &$value.repr {
MultiValuesRepr::Unset(from) => {
Err(DataConversionError::missing(*from, T::DATA_TYPE).into())
}
$(
$(#[$cfg])*
MultiValuesRepr::$variant(values) => {
DataConverters::from(values)
.to_vec_in($session)
.map_err(ValueError::from)
}
)+
}
};
}
#[inline(always)]
#[cfg(feature = "converter")]
fn convert_first_with<'a, T, I>(
values: DataConverters<I>,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<T>
where
T: DataConversionTarget,
I: Iterator,
I::Item: Into<DataConverter<'a>>,
{
values.to_first_with(policy, limits).map_err(ValueError::from)
}
#[inline(always)]
#[cfg(feature = "converter")]
fn convert_values_with<'a, T, I>(
values: DataConverters<I>,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
I: Iterator,
I::Item: Into<DataConverter<'a>>,
{
values.to_vec_with(policy, limits).map_err(ValueError::from)
}
#[cfg(feature = "converter")]
impl MultiValues {
fn contextual_conversion_error(&self, error: ValueError, first: bool) -> ValueError {
let ValueError::Missing(missing) = error else {
return error;
};
let reason = if self.is_unset() {
crate::ValueMissingReason::UnsetCollection
} else if self.is_empty() {
crate::ValueMissingReason::EmptyCollection
} else {
crate::ValueMissingReason::Conversion
};
let missing = missing.with_storage(self.data_type(), reason);
ValueError::Missing(if first { missing.with_first_index() } else { missing })
}
#[inline(always)]
pub fn to_first<T>(&self) -> ValueResult<T>
where
T: DataConversionTarget,
{
self.to_first_with(ConversionPolicy::default_ref(), ConversionLimits::default_ref())
}
#[inline]
pub fn to_first_or<T>(&self, default: impl IntoValueDefault<T>) -> ValueResult<T>
where
T: DataConversionTarget,
{
match self.to_first() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
Ok(default.into_value_default())
}
result => result,
}
}
#[inline]
pub fn to_first_or_else<T, F>(&self, default: F) -> ValueResult<T>
where
T: DataConversionTarget,
F: FnOnce() -> T,
{
match self.to_first() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
result => result,
}
}
pub fn to_first_with<T>(&self, policy: &ConversionPolicy, limits: &ConversionLimits) -> ValueResult<T>
where
T: DataConversionTarget,
{
for_each_value_type!(multi_values_convert_first_match, self, policy, limits)
.map_err(|error| self.contextual_conversion_error(error, true))
}
pub fn to_first_in<T>(&self, session: &mut ConversionSession<'_>) -> ValueResult<T>
where
T: DataConversionTarget,
{
for_each_value_type!(multi_values_convert_first_in_match, self, session)
.map_err(|error| self.contextual_conversion_error(error, true))
}
#[inline]
pub fn to_first_or_with<T>(
&self,
default: impl IntoValueDefault<T>,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<T>
where
T: DataConversionTarget,
{
match self.to_first_with(policy, limits) {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
Ok(default.into_value_default())
}
result => result,
}
}
#[inline]
pub fn to_first_or_else_with<T, F>(
&self,
default: F,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<T>
where
T: DataConversionTarget,
F: FnOnce() -> T,
{
match self.to_first_with(policy, limits) {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
result => result,
}
}
pub fn to_list<T>(&self) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
{
self.to_list_with(ConversionPolicy::default_ref(), ConversionLimits::default_ref())
}
#[inline]
pub fn to_list_or<T>(&self, default: impl IntoValueDefault<Vec<T>>) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
{
match self.to_list() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
Ok(default.into_value_default())
}
result => result,
}
}
#[inline]
pub fn to_list_or_else<T, F>(&self, default: F) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
F: FnOnce() -> Vec<T>,
{
match self.to_list() {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
result => result,
}
}
pub fn to_list_with<T>(&self, policy: &ConversionPolicy, limits: &ConversionLimits) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
{
for_each_value_type!(multi_values_convert_list_match, self, policy, limits)
.map_err(|error| self.contextual_conversion_error(error, false))
}
pub fn to_list_in<T>(&self, session: &mut ConversionSession<'_>) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
{
for_each_value_type!(multi_values_convert_list_in_match, self, session)
.map_err(|error| self.contextual_conversion_error(error, false))
}
#[inline]
pub fn to_list_or_with<T>(
&self,
default: impl IntoValueDefault<Vec<T>>,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
{
match self.to_list_with(policy, limits) {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => {
Ok(default.into_value_default())
}
result => result,
}
}
#[inline]
pub fn to_list_or_else_with<T, F>(
&self,
default: F,
policy: &ConversionPolicy,
limits: &ConversionLimits,
) -> ValueResult<Vec<T>>
where
T: DataConversionTarget,
F: FnOnce() -> Vec<T>,
{
match self.to_list_with(policy, limits) {
Err(ValueError::Missing(missing)) if missing.is_defaultable_for_conversion() => Ok(default()),
result => result,
}
}
}
impl MultiValues {
impl_get_first_value! {
copy: get_first_bool, Bool, bool, DataType::Bool
}
impl_get_first_value! {
copy: get_first_char, Char, char, DataType::Char
}
impl_get_first_value! {
copy: get_first_int8, Int8, i8, DataType::Int8
}
impl_get_first_value! {
copy: get_first_int16, Int16, i16, DataType::Int16
}
impl_get_first_value! {
copy: get_first_int32, Int32, i32, DataType::Int32
}
impl_get_first_value! {
copy: get_first_int64, Int64, i64, DataType::Int64
}
impl_get_first_value! {
copy: get_first_int128, Int128, i128, DataType::Int128
}
impl_get_first_value! {
copy: get_first_uint8, UInt8, u8, DataType::UInt8
}
impl_get_first_value! {
copy: get_first_uint16, UInt16, u16, DataType::UInt16
}
impl_get_first_value! {
copy: get_first_uint32, UInt32, u32, DataType::UInt32
}
impl_get_first_value! {
copy: get_first_uint64, UInt64, u64, DataType::UInt64
}
impl_get_first_value! {
copy: get_first_uint128, UInt128, u128, DataType::UInt128
}
impl_get_first_value! {
copy: get_first_float32, Float32, f32, DataType::Float32
}
impl_get_first_value! {
copy: get_first_float64, Float64, f64, DataType::Float64
}
impl_get_first_value! {
ref: get_first_string, String, &str, DataType::String, |s: &String| s.as_str()
}
impl_get_first_value! {
#[cfg(feature = "chrono")]
copy: get_first_date, Date, NaiveDate, DataType::Date
}
impl_get_first_value! {
#[cfg(feature = "chrono")]
copy: get_first_time, Time, NaiveTime, DataType::Time
}
impl_get_first_value! {
#[cfg(feature = "chrono")]
copy: get_first_datetime, DateTime, NaiveDateTime, DataType::DateTime
}
impl_get_first_value! {
#[cfg(feature = "chrono")]
copy: get_first_instant, Instant, DateTime<Utc>, DataType::Instant
}
impl_get_first_value! {
#[cfg(feature = "big-integer")]
ref: get_first_biginteger, BigInteger, BigInt, DataType::BigInteger, |v: &BigInt| v.clone()
}
impl_get_first_value! {
#[cfg(feature = "big-decimal")]
ref: get_first_bigdecimal, BigDecimal, BigDecimal, DataType::BigDecimal, |v: &BigDecimal| v.clone()
}
impl_get_first_value! {
copy: get_first_duration, Duration, Duration, DataType::Duration
}
impl_get_first_value! {
#[cfg(feature = "url")]
ref: get_first_url, Url, Url, DataType::Url, |v: &Url| v.clone()
}
impl_get_first_value! {
ref: get_first_string_map, StringMap, HashMap<String, String>, DataType::StringMap, |v: &HashMap<String, String>| v.clone()
}
impl_get_first_value! {
#[cfg(feature = "json")]
ref: get_first_json, Json, serde_json::Value, DataType::Json, |v: &serde_json::Value| v.clone()
}
impl_get_multi_values! {
slice: get_bools, Bool, bool, DataType::Bool
}
impl_get_multi_values! {
slice: get_chars, Char, char, DataType::Char
}
impl_get_multi_values! {
slice: get_int8s, Int8, i8, DataType::Int8
}
impl_get_multi_values! {
slice: get_int16s, Int16, i16, DataType::Int16
}
impl_get_multi_values! {
slice: get_int32s, Int32, i32, DataType::Int32
}
impl_get_multi_values! {
slice: get_int64s, Int64, i64, DataType::Int64
}
impl_get_multi_values! {
slice: get_int128s, Int128, i128, DataType::Int128
}
impl_get_multi_values! {
slice: get_uint8s, UInt8, u8, DataType::UInt8
}
impl_get_multi_values! {
slice: get_uint16s, UInt16, u16, DataType::UInt16
}
impl_get_multi_values! {
slice: get_uint32s, UInt32, u32, DataType::UInt32
}
impl_get_multi_values! {
slice: get_uint64s, UInt64, u64, DataType::UInt64
}
impl_get_multi_values! {
slice: get_uint128s, UInt128, u128, DataType::UInt128
}
impl_get_multi_values! {
slice: get_float32s, Float32, f32, DataType::Float32
}
impl_get_multi_values! {
slice: get_float64s, Float64, f64, DataType::Float64
}
impl_get_multi_values! {
vec: get_strings, String, String, DataType::String
}
impl_get_multi_values! {
#[cfg(feature = "chrono")]
slice: get_dates, Date, NaiveDate, DataType::Date
}
impl_get_multi_values! {
#[cfg(feature = "chrono")]
slice: get_times, Time, NaiveTime, DataType::Time
}
impl_get_multi_values! {
#[cfg(feature = "chrono")]
slice: get_datetimes, DateTime, NaiveDateTime, DataType::DateTime
}
impl_get_multi_values! {
#[cfg(feature = "chrono")]
slice: get_instants, Instant, DateTime<Utc>, DataType::Instant
}
impl_get_multi_values! {
#[cfg(feature = "big-integer")]
vec: get_bigintegers, BigInteger, BigInt, DataType::BigInteger
}
impl_get_multi_values! {
#[cfg(feature = "big-decimal")]
vec: get_bigdecimals, BigDecimal, BigDecimal, DataType::BigDecimal
}
impl_get_multi_values! {
slice: get_durations, Duration, Duration, DataType::Duration
}
impl_get_multi_values! {
#[cfg(feature = "url")]
vec: get_urls, Url, Url, DataType::Url
}
impl_get_multi_values! {
vec: get_string_maps, StringMap, HashMap<String, String>, DataType::StringMap
}
impl_get_multi_values! {
#[cfg(feature = "json")]
vec: get_jsons, Json, serde_json::Value, DataType::Json
}
}