diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/serde_with/src/de | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/serde_with/src/de')
-rw-r--r-- | third_party/rust/serde_with/src/de/duplicates.rs | 223 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/de/impls.rs | 1937 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/de/mod.rs | 158 |
3 files changed, 2318 insertions, 0 deletions
diff --git a/third_party/rust/serde_with/src/de/duplicates.rs b/third_party/rust/serde_with/src/de/duplicates.rs new file mode 100644 index 0000000000..a03dfba2f5 --- /dev/null +++ b/third_party/rust/serde_with/src/de/duplicates.rs @@ -0,0 +1,223 @@ +use super::impls::{foreach_map_create, foreach_set_create}; +use crate::{ + duplicate_key_impls::{ + DuplicateInsertsFirstWinsMap, DuplicateInsertsLastWinsSet, PreventDuplicateInsertsMap, + PreventDuplicateInsertsSet, + }, + prelude::*, + MapFirstKeyWins, MapPreventDuplicates, SetLastValueWins, SetPreventDuplicates, +}; +#[cfg(feature = "indexmap_1")] +use indexmap_1::{IndexMap, IndexSet}; + +struct SetPreventDuplicatesVisitor<SET, T, TAs>(PhantomData<(SET, T, TAs)>); + +impl<'de, SET, T, TAs> Visitor<'de> for SetPreventDuplicatesVisitor<SET, T, TAs> +where + SET: PreventDuplicateInsertsSet<T>, + TAs: DeserializeAs<'de, T>, +{ + type Value = SET; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence") + } + + #[inline] + fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + let mut values = Self::Value::new(access.size_hint()); + + while let Some(value) = access.next_element::<DeserializeAsWrap<T, TAs>>()? { + if !values.insert(value.into_inner()) { + return Err(DeError::custom("invalid entry: found duplicate value")); + }; + } + + Ok(values) + } +} + +struct SetLastValueWinsVisitor<SET, T, TAs>(PhantomData<(SET, T, TAs)>); + +impl<'de, SET, T, TAs> Visitor<'de> for SetLastValueWinsVisitor<SET, T, TAs> +where + SET: DuplicateInsertsLastWinsSet<T>, + TAs: DeserializeAs<'de, T>, +{ + type Value = SET; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence") + } + + #[inline] + fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + let mut values = Self::Value::new(access.size_hint()); + + while let Some(value) = access.next_element::<DeserializeAsWrap<T, TAs>>()? { + values.replace(value.into_inner()); + } + + Ok(values) + } +} + +#[cfg(feature = "alloc")] +macro_rules! set_impl { + ( + $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)* )* >, + $with_capacity:expr, + $append:ident + ) => { + impl<'de, T, TAs $(, $typaram)*> DeserializeAs<'de, $ty<T $(, $typaram)*>> for SetPreventDuplicates<TAs> + where + TAs: DeserializeAs<'de, T>, + $(T: $tbound1 $(+ $tbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty<T $(, $typaram)*>, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_seq(SetPreventDuplicatesVisitor::<$ty<T $(, $typaram)*>, T, TAs>( + PhantomData, + )) + } + } + + impl<'de, T, TAs $(, $typaram)*> DeserializeAs<'de, $ty<T $(, $typaram)*>> for SetLastValueWins<TAs> + where + TAs: DeserializeAs<'de, T>, + $(T: $tbound1 $(+ $tbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty<T $(, $typaram)*>, D::Error> + where + D: Deserializer<'de>, + { + deserializer + .deserialize_seq(SetLastValueWinsVisitor::<$ty<T $(, $typaram)*>, T, TAs>(PhantomData)) + } + } + } +} +foreach_set_create!(set_impl); + +struct MapPreventDuplicatesVisitor<MAP, K, KAs, V, VAs>(PhantomData<(MAP, K, KAs, V, VAs)>); + +impl<'de, MAP, K, KAs, V, VAs> Visitor<'de> for MapPreventDuplicatesVisitor<MAP, K, KAs, V, VAs> +where + MAP: PreventDuplicateInsertsMap<K, V>, + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, +{ + type Value = MAP; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + let mut values = Self::Value::new(access.size_hint()); + + while let Some((key, value)) = + access.next_entry::<DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>>()? + { + if !values.insert(key.into_inner(), value.into_inner()) { + return Err(DeError::custom("invalid entry: found duplicate key")); + }; + } + + Ok(values) + } +} + +struct MapFirstKeyWinsVisitor<MAP, K, KAs, V, VAs>(PhantomData<(MAP, K, KAs, V, VAs)>); + +impl<'de, MAP, K, KAs, V, VAs> Visitor<'de> for MapFirstKeyWinsVisitor<MAP, K, KAs, V, VAs> +where + MAP: DuplicateInsertsFirstWinsMap<K, V>, + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, +{ + type Value = MAP; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + let mut values = Self::Value::new(access.size_hint()); + + while let Some((key, value)) = + access.next_entry::<DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>>()? + { + values.insert(key.into_inner(), value.into_inner()); + } + + Ok(values) + } +} + +#[cfg(feature = "alloc")] +macro_rules! map_impl { + ( + $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, + $with_capacity:expr + ) => { + impl<'de, K, V, KAs, VAs $(, $typaram)*> DeserializeAs<'de, $ty<K, V $(, $typaram)*>> + for MapPreventDuplicates<KAs, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + $(K: $kbound1 $(+ $kbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty<K, V $(, $typaram)*>, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_map(MapPreventDuplicatesVisitor::< + $ty<K, V $(, $typaram)*>, + K, + KAs, + V, + VAs, + >(PhantomData)) + } + } + + impl<'de, K, V, KAs, VAs $(, $typaram)*> DeserializeAs<'de, $ty<K, V $(, $typaram)*>> + for MapFirstKeyWins<KAs, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + $(K: $kbound1 $(+ $kbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty<K, V $(, $typaram)*>, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_map(MapFirstKeyWinsVisitor::<$ty<K, V $(, $typaram)*>, K, KAs, V, VAs>( + PhantomData, + )) + } + } + }; +} +foreach_map_create!(map_impl); diff --git a/third_party/rust/serde_with/src/de/impls.rs b/third_party/rust/serde_with/src/de/impls.rs new file mode 100644 index 0000000000..066ad57490 --- /dev/null +++ b/third_party/rust/serde_with/src/de/impls.rs @@ -0,0 +1,1937 @@ +use crate::{formats::*, prelude::*}; +#[cfg(feature = "indexmap_1")] +use indexmap_1::{IndexMap, IndexSet}; + +/////////////////////////////////////////////////////////////////////////////// +// Helper macro used internally + +#[cfg(feature = "alloc")] +type BoxedSlice<T> = Box<[T]>; + +macro_rules! foreach_map { + ($m:ident) => { + #[cfg(feature = "alloc")] + $m!(BTreeMap<K: Ord, V>); + #[cfg(feature = "std")] + $m!(HashMap<K: Eq + Hash, V, H: Sized>); + #[cfg(all(feature = "std", feature = "indexmap_1"))] + $m!(IndexMap<K: Eq + Hash, V, H: Sized>); + }; +} +pub(crate) use foreach_map; + +macro_rules! foreach_map_create { + ($m:ident) => { + #[cfg(feature = "alloc")] + $m!(BTreeMap<K: Ord, V>, + (|_size| BTreeMap::new())); + #[cfg(feature = "std")] + $m!(HashMap<K: Eq + Hash, V, S: BuildHasher + Default>, + (|size| HashMap::with_capacity_and_hasher(size, Default::default()))); + #[cfg(feature = "indexmap_1")] + $m!(IndexMap<K: Eq + Hash, V, S: BuildHasher + Default>, + (|size| IndexMap::with_capacity_and_hasher(size, Default::default()))); + } +} +pub(crate) use foreach_map_create; + +macro_rules! foreach_set { + ($m:ident) => { + #[cfg(feature = "alloc")] + $m!(BTreeSet<(K, V): Ord>); + #[cfg(feature = "std")] + $m!(HashSet<(K, V): Eq + Hash>); + #[cfg(all(feature = "std", feature = "indexmap_1"))] + $m!(IndexSet<(K, V): Eq + Hash>); + } +} +pub(crate) use foreach_set; + +macro_rules! foreach_set_create { + ($m:ident) => { + #[cfg(feature = "alloc")] + $m!(BTreeSet<T: Ord>, (|_| BTreeSet::new()), insert); + #[cfg(feature = "std")] + $m!( + HashSet<T: Eq + Hash, S: BuildHasher + Default>, + (|size| HashSet::with_capacity_and_hasher(size, S::default())), + insert + ); + #[cfg(feature = "indexmap_1")] + $m!( + IndexSet<T: Eq + Hash, S: BuildHasher + Default>, + (|size| IndexSet::with_capacity_and_hasher(size, S::default())), + insert + ); + } +} +pub(crate) use foreach_set_create; + +macro_rules! foreach_seq { + ($m:ident) => { + foreach_set!($m); + + #[cfg(feature = "alloc")] + $m!(BinaryHeap<(K, V): Ord>); + #[cfg(feature = "alloc")] + $m!(LinkedList<(K, V)>); + #[cfg(feature = "alloc")] + $m!(Vec<(K, V)>); + #[cfg(feature = "alloc")] + $m!(VecDeque<(K, V)>); + } +} +pub(crate) use foreach_seq; + +macro_rules! foreach_seq_create { + ($m:ident) => { + foreach_set_create!($m); + + #[cfg(feature = "alloc")] + $m!( + BinaryHeap<T: Ord>, + (|size| BinaryHeap::with_capacity(size)), + push + ); + #[cfg(feature = "alloc")] + $m!(BoxedSlice<T>, (|size| Vec::with_capacity(size)), push); + #[cfg(feature = "alloc")] + $m!(LinkedList<T>, (|_| LinkedList::new()), push_back); + #[cfg(feature = "alloc")] + $m!(Vec<T>, (|size| Vec::with_capacity(size)), push); + #[cfg(feature = "alloc")] + $m!( + VecDeque<T>, + (|size| VecDeque::with_capacity(size)), + push_back + ); + }; +} +pub(crate) use foreach_seq_create; + +/////////////////////////////////////////////////////////////////////////////// +// region: Simple Wrapper types (e.g., Box, Option) + +#[cfg(feature = "alloc")] +impl<'de, T, U> DeserializeAs<'de, Box<T>> for Box<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Box<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(Box::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +impl<'de, T, U> DeserializeAs<'de, Option<T>> for Option<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Option<T>, D::Error> + where + D: Deserializer<'de>, + { + struct OptionVisitor<T, U>(PhantomData<(T, U)>); + + impl<'de, T, U> Visitor<'de> for OptionVisitor<T, U> + where + U: DeserializeAs<'de, T>, + { + type Value = Option<T>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("option") + } + + #[inline] + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(None) + } + + #[inline] + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(None) + } + + #[inline] + fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: Deserializer<'de>, + { + U::deserialize_as(deserializer).map(Some) + } + } + + deserializer.deserialize_option(OptionVisitor::<T, U>(PhantomData)) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, U> DeserializeAs<'de, Rc<T>> for Rc<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Rc<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(Rc::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, U> DeserializeAs<'de, RcWeak<T>> for RcWeak<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<RcWeak<T>, D::Error> + where + D: Deserializer<'de>, + { + DeserializeAsWrap::<Option<Rc<T>>, Option<Rc<U>>>::deserialize(deserializer)?; + Ok(RcWeak::new()) + } +} + +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +impl<'de, T, U> DeserializeAs<'de, Arc<T>> for Arc<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Arc<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(Arc::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +impl<'de, T, U> DeserializeAs<'de, ArcWeak<T>> for ArcWeak<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<ArcWeak<T>, D::Error> + where + D: Deserializer<'de>, + { + DeserializeAsWrap::<Option<Arc<T>>, Option<Arc<U>>>::deserialize(deserializer)?; + Ok(ArcWeak::new()) + } +} + +impl<'de, T, U> DeserializeAs<'de, Cell<T>> for Cell<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Cell<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(Cell::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +impl<'de, T, U> DeserializeAs<'de, RefCell<T>> for RefCell<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<RefCell<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(RefCell::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +#[cfg(feature = "std")] +impl<'de, T, U> DeserializeAs<'de, Mutex<T>> for Mutex<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Mutex<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(Mutex::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +#[cfg(feature = "std")] +impl<'de, T, U> DeserializeAs<'de, RwLock<T>> for RwLock<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<RwLock<T>, D::Error> + where + D: Deserializer<'de>, + { + Ok(RwLock::new( + DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), + )) + } +} + +impl<'de, T, TAs, E, EAs> DeserializeAs<'de, Result<T, E>> for Result<TAs, EAs> +where + TAs: DeserializeAs<'de, T>, + EAs: DeserializeAs<'de, E>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Result<T, E>, D::Error> + where + D: Deserializer<'de>, + { + Ok( + match Result::<DeserializeAsWrap<T, TAs>, DeserializeAsWrap<E, EAs>>::deserialize( + deserializer, + )? { + Ok(value) => Ok(value.into_inner()), + Err(err) => Err(err.into_inner()), + }, + ) + } +} + +impl<'de, T, As, const N: usize> DeserializeAs<'de, [T; N]> for [As; N] +where + As: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<[T; N], D::Error> + where + D: Deserializer<'de>, + { + struct ArrayVisitor<T, const M: usize>(PhantomData<T>); + + impl<'de, T, As, const M: usize> Visitor<'de> for ArrayVisitor<DeserializeAsWrap<T, As>, M> + where + As: DeserializeAs<'de, T>, + { + type Value = [T; M]; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_fmt(format_args!("an array of size {M}")) + } + + fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + utils::array_from_iterator( + utils::SeqIter::new(seq).map( + |res: Result<DeserializeAsWrap<T, As>, A::Error>| { + res.map(|t| t.into_inner()) + }, + ), + &self, + ) + } + } + + deserializer.deserialize_tuple(N, ArrayVisitor::<DeserializeAsWrap<T, As>, N>(PhantomData)) + } +} + +// endregion +/////////////////////////////////////////////////////////////////////////////// +// region: Collection Types (e.g., Maps, Sets, Vec) + +#[cfg(feature = "alloc")] +macro_rules! seq_impl { + ( + $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)* )* >, + $with_capacity:expr, + $append:ident + ) => { + // Fix for clippy regression in macros on stable + // The bug no longer exists on nightly + // https://github.com/rust-lang/rust-clippy/issues/7768 + #[allow(clippy::semicolon_if_nothing_returned)] + impl<'de, T, U $(, $typaram)*> DeserializeAs<'de, $ty<T $(, $typaram)*>> for $ty<U $(, $typaram)*> + where + U: DeserializeAs<'de, T>, + $(T: $tbound1 $(+ $tbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty<T $(, $typaram)*>, D::Error> + where + D: Deserializer<'de>, + { + struct SeqVisitor<T, U $(, $typaram)*> { + marker: PhantomData<(T, U $(, $typaram)*)>, + } + + impl<'de, T, U $(, $typaram)*> Visitor<'de> for SeqVisitor<T, U $(, $typaram)*> + where + U: DeserializeAs<'de, T>, + $(T: $tbound1 $(+ $tbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + type Value = $ty<T $(, $typaram)*>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence") + } + + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + let mut values = ($with_capacity)(utils::size_hint_cautious(seq.size_hint())); + + while let Some(value) = seq + .next_element()? + .map(|v: DeserializeAsWrap<T, U>| v.into_inner()) + { + values.$append(value); + } + + Ok(values.into()) + } + } + + let visitor = SeqVisitor::<T, U $(, $typaram)*> { + marker: PhantomData, + }; + deserializer.deserialize_seq(visitor) + } + } + }; +} +foreach_seq_create!(seq_impl); + +#[cfg(feature = "alloc")] +macro_rules! map_impl { + ( + $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, + $with_capacity:expr + ) => { + // Fix for clippy regression in macros on stable + // The bug no longer exists on nightly + // https://github.com/rust-lang/rust-clippy/issues/7768 + #[allow(clippy::semicolon_if_nothing_returned)] + impl<'de, K, V, KU, VU $(, $typaram)*> DeserializeAs<'de, $ty<K, V $(, $typaram)*>> for $ty<KU, VU $(, $typaram)*> + where + KU: DeserializeAs<'de, K>, + VU: DeserializeAs<'de, V>, + $(K: $kbound1 $(+ $kbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty<K, V $(, $typaram)*>, D::Error> + where + D: Deserializer<'de>, + { + struct MapVisitor<K, V, KU, VU $(, $typaram)*>(PhantomData<(K, V, KU, VU $(, $typaram)*)>); + + impl<'de, K, V, KU, VU $(, $typaram)*> Visitor<'de> for MapVisitor<K, V, KU, VU $(, $typaram)*> + where + KU: DeserializeAs<'de, K>, + VU: DeserializeAs<'de, V>, + $(K: $kbound1 $(+ $kbound2)*,)* + $($typaram: $bound1 $(+ $bound2)*),* + { + type Value = $ty<K, V $(, $typaram)*>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + let mut values = ($with_capacity)(utils::size_hint_cautious(map.size_hint())); + + while let Some((key, value)) = (map.next_entry())?.map(|(k, v): (DeserializeAsWrap::<K, KU>, DeserializeAsWrap::<V, VU>)| (k.into_inner(), v.into_inner())) { + values.insert(key, value); + } + + Ok(values) + } + } + + let visitor = MapVisitor::<K, V, KU, VU $(, $typaram)*> (PhantomData); + deserializer.deserialize_map(visitor) + } + } + } +} +foreach_map_create!(map_impl); + +macro_rules! tuple_impl { + ($len:literal $($n:tt $t:ident $tas:ident)+) => { + impl<'de, $($t, $tas,)+> DeserializeAs<'de, ($($t,)+)> for ($($tas,)+) + where + $($tas: DeserializeAs<'de, $t>,)+ + { + fn deserialize_as<D>(deserializer: D) -> Result<($($t,)+), D::Error> + where + D: Deserializer<'de>, + { + struct TupleVisitor<$($t,)+>(PhantomData<($($t,)+)>); + + impl<'de, $($t, $tas,)+> Visitor<'de> + for TupleVisitor<$(DeserializeAsWrap<$t, $tas>,)+> + where + $($tas: DeserializeAs<'de, $t>,)+ + { + type Value = ($($t,)+); + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str(concat!("a tuple of size ", $len)) + } + + #[allow(non_snake_case)] + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + $( + let $t: DeserializeAsWrap<$t, $tas> = match seq.next_element()? { + Some(value) => value, + None => return Err(DeError::invalid_length($n, &self)), + }; + )+ + + Ok(($($t.into_inner(),)+)) + } + } + + deserializer.deserialize_tuple( + $len, + TupleVisitor::<$(DeserializeAsWrap<$t, $tas>,)+>(PhantomData), + ) + } + } + }; +} + +tuple_impl!(1 0 T0 As0); +tuple_impl!(2 0 T0 As0 1 T1 As1); +tuple_impl!(3 0 T0 As0 1 T1 As1 2 T2 As2); +tuple_impl!(4 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3); +tuple_impl!(5 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4); +tuple_impl!(6 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5); +tuple_impl!(7 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6); +tuple_impl!(8 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7); +tuple_impl!(9 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8); +tuple_impl!(10 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9); +tuple_impl!(11 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9 10 T10 As10); +tuple_impl!(12 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9 10 T10 As10 11 T11 As11); +tuple_impl!(13 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9 10 T10 As10 11 T11 As11 12 T12 As12); +tuple_impl!(14 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9 10 T10 As10 11 T11 As11 12 T12 As12 13 T13 As13); +tuple_impl!(15 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9 10 T10 As10 11 T11 As11 12 T12 As12 13 T13 As13 14 T14 As14); +tuple_impl!(16 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7 T7 As7 8 T8 As8 9 T9 As9 10 T10 As10 11 T11 As11 12 T12 As12 13 T13 As13 14 T14 As14 15 T15 As15); + +#[cfg(feature = "alloc")] +macro_rules! map_as_tuple_seq_intern { + ($tyorig:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident <(KAs, VAs)>) => { + impl<'de, K, KAs, V, VAs> DeserializeAs<'de, $tyorig<K, V>> for $ty<(KAs, VAs)> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + $(K: $kbound1 $(+ $kbound2)*,)* + { + fn deserialize_as<D>(deserializer: D) -> Result<$tyorig<K, V>, D::Error> + where + D: Deserializer<'de>, + { + struct SeqVisitor<K, KAs, V, VAs> { + marker: PhantomData<(K, KAs, V, VAs)>, + } + + impl<'de, K, KAs, V, VAs> Visitor<'de> for SeqVisitor<K, KAs, V, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + $(K: $kbound1 $(+ $kbound2)*,)* + { + type Value = $tyorig<K, V>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence") + } + + #[inline] + fn visit_seq<A>(self, access: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + let iter = utils::SeqIter::new(access); + iter.map(|res| { + res.map( + |(k, v): (DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>)| { + (k.into_inner(), v.into_inner()) + }, + ) + }) + .collect() + } + } + + let visitor = SeqVisitor::<K, KAs, V, VAs> { + marker: PhantomData, + }; + deserializer.deserialize_seq(visitor) + } + } + }; +} +#[cfg(feature = "alloc")] +macro_rules! map_as_tuple_seq { + ($tyorig:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >) => { + map_as_tuple_seq_intern!($tyorig < K $(: $kbound1 $(+ $kbound2)*)* , V $(, $typaram : $bound1 $(+ $bound2)*)* > , Seq<(KAs, VAs)>); + #[cfg(feature = "alloc")] + map_as_tuple_seq_intern!($tyorig < K $(: $kbound1 $(+ $kbound2)*)* , V $(, $typaram : $bound1 $(+ $bound2)*)* >, Vec<(KAs, VAs)>); + } +} +foreach_map!(map_as_tuple_seq); + +#[cfg(feature = "alloc")] +macro_rules! tuple_seq_as_map_impl_intern { + ($tyorig:ident < (K, V) $(: $($bound:ident $(+)?)+)?>, $ty:ident <KAs, VAs>) => { + #[allow(clippy::implicit_hasher)] + impl<'de, K, KAs, V, VAs> DeserializeAs<'de, $tyorig < (K, V) >> for $ty<KAs, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + (K, V): $($($bound +)*)*, + { + fn deserialize_as<D>(deserializer: D) -> Result<$tyorig < (K, V) >, D::Error> + where + D: Deserializer<'de>, + { + struct MapVisitor<K, KAs, V, VAs> { + marker: PhantomData<(K, KAs, V, VAs)>, + } + + impl<'de, K, KAs, V, VAs> Visitor<'de> for MapVisitor<K, KAs, V, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + (K, V): $($($bound +)*)*, + { + type Value = $tyorig < (K, V) >; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_map<A>(self, access: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + let iter = utils::MapIter::new(access); + iter.map(|res| { + res.map( + |(k, v): (DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>)| { + (k.into_inner(), v.into_inner()) + }, + ) + }) + .collect() + } + } + + let visitor = MapVisitor::<K, KAs, V, VAs> { + marker: PhantomData, + }; + deserializer.deserialize_map(visitor) + } + } + } +} +#[cfg(feature = "alloc")] +macro_rules! tuple_seq_as_map_impl { + ($tyorig:ident < (K, V) $(: $($bound:ident $(+)?)+)?>) => { + tuple_seq_as_map_impl_intern!($tyorig < (K, V) $(: $($bound +)+)? >, Map<KAs, VAs>); + #[cfg(feature = "alloc")] + tuple_seq_as_map_impl_intern!($tyorig < (K, V) $(: $($bound +)+)? >, BTreeMap<KAs, VAs>); + #[cfg(feature = "std")] + tuple_seq_as_map_impl_intern!($tyorig < (K, V) $(: $($bound +)+)? >, HashMap<KAs, VAs>); + } +} +foreach_seq!(tuple_seq_as_map_impl); + +// Option does not implement FromIterator directly, so we need a different implementation +#[cfg(feature = "alloc")] +macro_rules! tuple_seq_as_map_option_impl { + ($ty:ident) => { + #[allow(clippy::implicit_hasher)] + impl<'de, K, KAs, V, VAs> DeserializeAs<'de, Option<(K, V)>> for $ty<KAs, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + { + fn deserialize_as<D>(deserializer: D) -> Result<Option<(K, V)>, D::Error> + where + D: Deserializer<'de>, + { + struct MapVisitor<K, KAs, V, VAs> { + marker: PhantomData<(K, KAs, V, VAs)>, + } + + impl<'de, K, KAs, V, VAs> Visitor<'de> for MapVisitor<K, KAs, V, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + { + type Value = Option<(K, V)>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map of size 1") + } + + #[inline] + fn visit_map<A>(self, access: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + let iter = utils::MapIter::new(access); + iter.map(|res| { + res.map( + |(k, v): (DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>)| { + (k.into_inner(), v.into_inner()) + }, + ) + }) + .next() + .transpose() + } + } + + let visitor = MapVisitor::<K, KAs, V, VAs> { + marker: PhantomData, + }; + deserializer.deserialize_map(visitor) + } + } + }; +} +#[cfg(feature = "alloc")] +tuple_seq_as_map_option_impl!(BTreeMap); +#[cfg(feature = "std")] +tuple_seq_as_map_option_impl!(HashMap); + +macro_rules! tuple_seq_as_map_arr { + ($ty:ident <KAs, VAs>) => { + #[allow(clippy::implicit_hasher)] + impl<'de, K, KAs, V, VAs, const N: usize> DeserializeAs<'de, [(K, V); N]> for $ty<KAs, VAs> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + { + fn deserialize_as<D>(deserializer: D) -> Result<[(K, V); N], D::Error> + where + D: Deserializer<'de>, + { + struct MapVisitor<K, KAs, V, VAs, const M: usize> { + marker: PhantomData<(K, KAs, V, VAs)>, + } + + impl<'de, K, KAs, V, VAs, const M: usize> Visitor<'de> for MapVisitor<K, KAs, V, VAs, M> + where + KAs: DeserializeAs<'de, K>, + VAs: DeserializeAs<'de, V>, + { + type Value = [(K, V); M]; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_fmt(format_args!("a map of length {}", M)) + } + + fn visit_map<A>(self, access: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + utils::array_from_iterator(utils::MapIter::new(access).map( + |res: Result<(DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>), A::Error>| { + res.map(|(k, v)| (k.into_inner(), v.into_inner())) + } + ), &self) + } + } + + let visitor = MapVisitor::<K, KAs, V, VAs, N> { + marker: PhantomData, + }; + deserializer.deserialize_map(visitor) + } + } + } +} +tuple_seq_as_map_arr!(Map<KAs, VAs>); +#[cfg(feature = "alloc")] +tuple_seq_as_map_arr!(BTreeMap<KAs, VAs>); +#[cfg(feature = "std")] +tuple_seq_as_map_arr!(HashMap<KAs, VAs>); + +// endregion +/////////////////////////////////////////////////////////////////////////////// +// region: Conversion types which cause different serialization behavior + +impl<'de, T: Deserialize<'de>> DeserializeAs<'de, T> for Same { + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + T::deserialize(deserializer) + } +} + +impl<'de, T> DeserializeAs<'de, T> for DisplayFromStr +where + T: FromStr, + T::Err: Display, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + struct Helper<S>(PhantomData<S>); + impl<'de, S> Visitor<'de> for Helper<S> + where + S: FromStr, + <S as FromStr>::Err: Display, + { + type Value = S; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "a string") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: DeError, + { + value.parse::<Self::Value>().map_err(DeError::custom) + } + } + + deserializer.deserialize_str(Helper(PhantomData)) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, U> DeserializeAs<'de, Vec<T>> for VecSkipError<U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Vec<T>, D::Error> + where + D: Deserializer<'de>, + { + enum GoodOrError<T, TAs> { + Good(T), + // Only here to consume the TAs generic + Error(PhantomData<TAs>), + } + + impl<'de, T, TAs> Deserialize<'de> for GoodOrError<T, TAs> + where + TAs: DeserializeAs<'de, T>, + { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let is_hr = deserializer.is_human_readable(); + let content: content::de::Content<'de> = Deserialize::deserialize(deserializer)?; + + Ok( + match <DeserializeAsWrap<T, TAs>>::deserialize( + content::de::ContentDeserializer::<D::Error>::new(content, is_hr), + ) { + Ok(elem) => GoodOrError::Good(elem.into_inner()), + Err(_) => GoodOrError::Error(PhantomData), + }, + ) + } + } + + struct SeqVisitor<T, U> { + marker: PhantomData<T>, + marker2: PhantomData<U>, + } + + impl<'de, T, TAs> Visitor<'de> for SeqVisitor<T, TAs> + where + TAs: DeserializeAs<'de, T>, + { + type Value = Vec<T>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence") + } + + fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + utils::SeqIter::new(seq) + .filter_map(|res: Result<GoodOrError<T, TAs>, A::Error>| match res { + Ok(GoodOrError::Good(value)) => Some(Ok(value)), + Ok(GoodOrError::Error(_)) => None, + Err(err) => Some(Err(err)), + }) + .collect() + } + } + + let visitor = SeqVisitor::<T, U> { + marker: PhantomData, + marker2: PhantomData, + }; + deserializer.deserialize_seq(visitor) + } +} + +impl<'de, Str> DeserializeAs<'de, Option<Str>> for NoneAsEmptyString +where + Str: FromStr, + Str::Err: Display, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Option<Str>, D::Error> + where + D: Deserializer<'de>, + { + struct OptionStringEmptyNone<S>(PhantomData<S>); + impl<'de, S> Visitor<'de> for OptionStringEmptyNone<S> + where + S: FromStr, + S::Err: Display, + { + type Value = Option<S>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a string") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: DeError, + { + match value { + "" => Ok(None), + v => S::from_str(v).map(Some).map_err(DeError::custom), + } + } + + // handles the `null` case + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(None) + } + } + + deserializer.deserialize_any(OptionStringEmptyNone(PhantomData)) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, TAs> DeserializeAs<'de, T> for DefaultOnError<TAs> +where + TAs: DeserializeAs<'de, T>, + T: Default, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + let is_hr = deserializer.is_human_readable(); + let content: content::de::Content<'de> = match Deserialize::deserialize(deserializer) { + Ok(content) => content, + Err(_) => return Ok(Default::default()), + }; + + Ok( + match <DeserializeAsWrap<T, TAs>>::deserialize(content::de::ContentDeserializer::< + D::Error, + >::new(content, is_hr)) + { + Ok(elem) => elem.into_inner(), + Err(_) => Default::default(), + }, + ) + } +} + +#[cfg(feature = "alloc")] +impl<'de> DeserializeAs<'de, Vec<u8>> for BytesOrString { + fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error> + where + D: Deserializer<'de>, + { + struct BytesOrStringVisitor; + impl<'de> Visitor<'de> for BytesOrStringVisitor { + type Value = Vec<u8>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a list of bytes or a string") + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> { + Ok(v.to_vec()) + } + + #[cfg(feature = "alloc")] + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> { + Ok(v) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> { + Ok(v.as_bytes().to_vec()) + } + + #[cfg(feature = "alloc")] + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> { + Ok(v.into_bytes()) + } + + fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + utils::SeqIter::new(seq).collect() + } + } + deserializer.deserialize_any(BytesOrStringVisitor) + } +} + +impl<'de, SEPARATOR, I, T> DeserializeAs<'de, I> for StringWithSeparator<SEPARATOR, T> +where + SEPARATOR: Separator, + I: FromIterator<T>, + T: FromStr, + T::Err: Display, +{ + fn deserialize_as<D>(deserializer: D) -> Result<I, D::Error> + where + D: Deserializer<'de>, + { + struct Helper<SEPARATOR, I, T>(PhantomData<(SEPARATOR, I, T)>); + + impl<'de, SEPARATOR, I, T> Visitor<'de> for Helper<SEPARATOR, I, T> + where + SEPARATOR: Separator, + I: FromIterator<T>, + T: FromStr, + T::Err: Display, + { + type Value = I; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "a string") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: DeError, + { + if value.is_empty() { + Ok(None.into_iter().collect()) + } else { + value + .split(SEPARATOR::separator()) + .map(FromStr::from_str) + .collect::<Result<_, _>>() + .map_err(DeError::custom) + } + } + } + + deserializer.deserialize_str(Helper::<SEPARATOR, I, T>(PhantomData)) + } +} + +#[cfg(feature = "std")] +macro_rules! use_signed_duration { + ( + $main_trait:ident $internal_trait:ident => + { + $ty:ty; $converter:ident => + $({ + $format:ty, $strictness:ty => + $($tbound:ident: $bound:ident $(,)?)* + })* + } + ) => { + $( + impl<'de, $($tbound,)*> DeserializeAs<'de, $ty> for $main_trait<$format, $strictness> + where + $($tbound: $bound,)* + { + fn deserialize_as<D>(deserializer: D) -> Result<$ty, D::Error> + where + D: Deserializer<'de>, + { + let dur: DurationSigned = $internal_trait::<$format, $strictness>::deserialize_as(deserializer)?; + dur.$converter::<D>() + } + } + )* + }; + ( + $( $main_trait:ident $internal_trait:ident, )+ => $rest:tt + ) => { + $( use_signed_duration!($main_trait $internal_trait => $rest); )+ + }; +} + +#[cfg(feature = "std")] +use_signed_duration!( + DurationSeconds DurationSeconds, + DurationMilliSeconds DurationMilliSeconds, + DurationMicroSeconds DurationMicroSeconds, + DurationNanoSeconds DurationNanoSeconds, + => { + Duration; to_std_duration => + {u64, Strict =>} + {f64, Strict =>} + {String, Strict =>} + {FORMAT, Flexible => FORMAT: Format} + } +); +#[cfg(feature = "std")] +use_signed_duration!( + DurationSecondsWithFrac DurationSecondsWithFrac, + DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac, + DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac, + DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac, + => { + Duration; to_std_duration => + {f64, Strict =>} + {String, Strict =>} + {FORMAT, Flexible => FORMAT: Format} + } +); + +#[cfg(feature = "std")] +use_signed_duration!( + TimestampSeconds DurationSeconds, + TimestampMilliSeconds DurationMilliSeconds, + TimestampMicroSeconds DurationMicroSeconds, + TimestampNanoSeconds DurationNanoSeconds, + => { + SystemTime; to_system_time => + {i64, Strict =>} + {f64, Strict =>} + {String, Strict =>} + {FORMAT, Flexible => FORMAT: Format} + } +); +#[cfg(feature = "std")] +use_signed_duration!( + TimestampSecondsWithFrac DurationSecondsWithFrac, + TimestampMilliSecondsWithFrac DurationMilliSecondsWithFrac, + TimestampMicroSecondsWithFrac DurationMicroSecondsWithFrac, + TimestampNanoSecondsWithFrac DurationNanoSecondsWithFrac, + => { + SystemTime; to_system_time => + {f64, Strict =>} + {String, Strict =>} + {FORMAT, Flexible => FORMAT: Format} + } +); + +impl<'de, T, U> DeserializeAs<'de, T> for DefaultOnNull<U> +where + U: DeserializeAs<'de, T>, + T: Default, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + Ok(Option::<U>::deserialize_as(deserializer)?.unwrap_or_default()) + } +} + +impl<'de> DeserializeAs<'de, &'de [u8]> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<&'de [u8], D::Error> + where + D: Deserializer<'de>, + { + <&'de [u8]>::deserialize(deserializer) + } +} + +// serde_bytes implementation for ByteBuf +// https://github.com/serde-rs/bytes/blob/cbae606b9dc225fc094b031cc84eac9493da2058/src/bytebuf.rs#L196 +// +// Implements: +// * visit_seq +// * visit_bytes +// * visit_byte_buf +// * visit_str +// * visit_string +#[cfg(feature = "alloc")] +impl<'de> DeserializeAs<'de, Vec<u8>> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error> + where + D: Deserializer<'de>, + { + struct VecVisitor; + + impl<'de> Visitor<'de> for VecVisitor { + type Value = Vec<u8>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + utils::SeqIter::new(seq).collect::<Result<_, _>>() + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v.to_vec()) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v.as_bytes().to_vec()) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v.into_bytes()) + } + } + + deserializer.deserialize_byte_buf(VecVisitor) + } +} + +#[cfg(feature = "alloc")] +impl<'de> DeserializeAs<'de, Box<[u8]>> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<Box<[u8]>, D::Error> + where + D: Deserializer<'de>, + { + <Bytes as DeserializeAs<'de, Vec<u8>>>::deserialize_as(deserializer) + .map(|vec| vec.into_boxed_slice()) + } +} + +// serde_bytes implementation for Cow<'a, [u8]> +// https://github.com/serde-rs/bytes/blob/cbae606b9dc225fc094b031cc84eac9493da2058/src/de.rs#L77 +// +// Implements: +// * visit_borrowed_bytes +// * visit_borrowed_str +// * visit_bytes +// * visit_str +// * visit_byte_buf +// * visit_string +// * visit_seq +#[cfg(feature = "alloc")] +impl<'de> DeserializeAs<'de, Cow<'de, [u8]>> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<Cow<'de, [u8]>, D::Error> + where + D: Deserializer<'de>, + { + struct CowVisitor; + + impl<'de> Visitor<'de> for CowVisitor { + type Value = Cow<'de, [u8]>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Borrowed(v.as_bytes())) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned(v.to_vec())) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned(v.as_bytes().to_vec())) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned(v)) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned(v.into_bytes())) + } + + fn visit_seq<V>(self, seq: V) -> Result<Self::Value, V::Error> + where + V: SeqAccess<'de>, + { + Ok(Cow::Owned( + utils::SeqIter::new(seq).collect::<Result<_, _>>()?, + )) + } + } + + deserializer.deserialize_bytes(CowVisitor) + } +} + +impl<'de, const N: usize> DeserializeAs<'de, [u8; N]> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<[u8; N], D::Error> + where + D: Deserializer<'de>, + { + struct ArrayVisitor<const M: usize>; + + impl<'de, const M: usize> Visitor<'de> for ArrayVisitor<M> { + type Value = [u8; M]; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_fmt(format_args!("an byte array of size {M}")) + } + + fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + utils::array_from_iterator(utils::SeqIter::new(seq), &self) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: DeError, + { + v.try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self)) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: DeError, + { + v.as_bytes() + .try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self)) + } + } + + deserializer.deserialize_bytes(ArrayVisitor::<N>) + } +} + +impl<'de, const N: usize> DeserializeAs<'de, &'de [u8; N]> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<&'de [u8; N], D::Error> + where + D: Deserializer<'de>, + { + struct ArrayVisitor<const M: usize>; + + impl<'de, const M: usize> Visitor<'de> for ArrayVisitor<M> { + type Value = &'de [u8; M]; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_fmt(format_args!("a borrowed byte array of size {M}")) + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: DeError, + { + v.try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self)) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: DeError, + { + v.as_bytes() + .try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self)) + } + } + + deserializer.deserialize_bytes(ArrayVisitor::<N>) + } +} + +#[cfg(feature = "alloc")] +impl<'de, const N: usize> DeserializeAs<'de, Cow<'de, [u8; N]>> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<Cow<'de, [u8; N]>, D::Error> + where + D: Deserializer<'de>, + { + struct CowVisitor<const M: usize>; + + impl<'de, const M: usize> Visitor<'de> for CowVisitor<M> { + type Value = Cow<'de, [u8; M]>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Borrowed( + v.try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self))?, + )) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Borrowed( + v.as_bytes() + .try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self))?, + )) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned( + v.to_vec() + .try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self))?, + )) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned( + v.as_bytes() + .to_vec() + .try_into() + .map_err(|_| DeError::invalid_length(v.len(), &self))?, + )) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: DeError, + { + let len = v.len(); + Ok(Cow::Owned( + v.try_into() + .map_err(|_| DeError::invalid_length(len, &self))?, + )) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: DeError, + { + let len = v.len(); + Ok(Cow::Owned( + v.into_bytes() + .try_into() + .map_err(|_| DeError::invalid_length(len, &self))?, + )) + } + + fn visit_seq<V>(self, seq: V) -> Result<Self::Value, V::Error> + where + V: SeqAccess<'de>, + { + Ok(Cow::Owned(utils::array_from_iterator( + utils::SeqIter::new(seq), + &self, + )?)) + } + } + + deserializer.deserialize_bytes(CowVisitor) + } +} + +#[cfg(feature = "alloc")] +impl<'de, const N: usize> DeserializeAs<'de, Box<[u8; N]>> for Bytes { + fn deserialize_as<D>(deserializer: D) -> Result<Box<[u8; N]>, D::Error> + where + D: Deserializer<'de>, + { + Bytes::deserialize_as(deserializer).map(Box::new) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, TAs, FORMAT> DeserializeAs<'de, Vec<T>> for OneOrMany<TAs, FORMAT> +where + TAs: DeserializeAs<'de, T>, + FORMAT: Format, +{ + fn deserialize_as<D>(deserializer: D) -> Result<Vec<T>, D::Error> + where + D: Deserializer<'de>, + { + let is_hr = deserializer.is_human_readable(); + let content: content::de::Content<'de> = Deserialize::deserialize(deserializer)?; + + let one_err: D::Error = match <DeserializeAsWrap<T, TAs>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(one) => return Ok(alloc::vec![one.into_inner()]), + Err(err) => err, + }; + let many_err: D::Error = match <DeserializeAsWrap<Vec<T>, Vec<TAs>>>::deserialize( + content::de::ContentDeserializer::new(content, is_hr), + ) { + Ok(many) => return Ok(many.into_inner()), + Err(err) => err, + }; + Err(DeError::custom(format_args!( + "OneOrMany could not deserialize any variant:\n One: {}\n Many: {}", + one_err, many_err + ))) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, TAs1> DeserializeAs<'de, T> for PickFirst<(TAs1,)> +where + TAs1: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + Ok(DeserializeAsWrap::<T, TAs1>::deserialize(deserializer)?.into_inner()) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, TAs1, TAs2> DeserializeAs<'de, T> for PickFirst<(TAs1, TAs2)> +where + TAs1: DeserializeAs<'de, T>, + TAs2: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + let is_hr = deserializer.is_human_readable(); + let content: content::de::Content<'de> = Deserialize::deserialize(deserializer)?; + + let first_err: D::Error = match <DeserializeAsWrap<T, TAs1>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(first) => return Ok(first.into_inner()), + Err(err) => err, + }; + let second_err: D::Error = match <DeserializeAsWrap<T, TAs2>>::deserialize( + content::de::ContentDeserializer::new(content, is_hr), + ) { + Ok(second) => return Ok(second.into_inner()), + Err(err) => err, + }; + Err(DeError::custom(format_args!( + "PickFirst could not deserialize any variant:\n First: {}\n Second: {}", + first_err, second_err + ))) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, TAs1, TAs2, TAs3> DeserializeAs<'de, T> for PickFirst<(TAs1, TAs2, TAs3)> +where + TAs1: DeserializeAs<'de, T>, + TAs2: DeserializeAs<'de, T>, + TAs3: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + let is_hr = deserializer.is_human_readable(); + let content: content::de::Content<'de> = Deserialize::deserialize(deserializer)?; + + let first_err: D::Error = match <DeserializeAsWrap<T, TAs1>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(first) => return Ok(first.into_inner()), + Err(err) => err, + }; + let second_err: D::Error = match <DeserializeAsWrap<T, TAs2>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(second) => return Ok(second.into_inner()), + Err(err) => err, + }; + let third_err: D::Error = match <DeserializeAsWrap<T, TAs3>>::deserialize( + content::de::ContentDeserializer::new(content, is_hr), + ) { + Ok(third) => return Ok(third.into_inner()), + Err(err) => err, + }; + Err(DeError::custom(format_args!( + "PickFirst could not deserialize any variant:\n First: {}\n Second: {}\n Third: {}", + first_err, second_err, third_err, + ))) + } +} + +#[cfg(feature = "alloc")] +impl<'de, T, TAs1, TAs2, TAs3, TAs4> DeserializeAs<'de, T> for PickFirst<(TAs1, TAs2, TAs3, TAs4)> +where + TAs1: DeserializeAs<'de, T>, + TAs2: DeserializeAs<'de, T>, + TAs3: DeserializeAs<'de, T>, + TAs4: DeserializeAs<'de, T>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + let is_hr = deserializer.is_human_readable(); + let content: content::de::Content<'de> = Deserialize::deserialize(deserializer)?; + + let first_err: D::Error = match <DeserializeAsWrap<T, TAs1>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(first) => return Ok(first.into_inner()), + Err(err) => err, + }; + let second_err: D::Error = match <DeserializeAsWrap<T, TAs2>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(second) => return Ok(second.into_inner()), + Err(err) => err, + }; + let third_err: D::Error = match <DeserializeAsWrap<T, TAs3>>::deserialize( + content::de::ContentRefDeserializer::new(&content, is_hr), + ) { + Ok(third) => return Ok(third.into_inner()), + Err(err) => err, + }; + let fourth_err: D::Error = match <DeserializeAsWrap<T, TAs4>>::deserialize( + content::de::ContentDeserializer::new(content, is_hr), + ) { + Ok(fourth) => return Ok(fourth.into_inner()), + Err(err) => err, + }; + Err(DeError::custom(format_args!( + "PickFirst could not deserialize any variant:\n First: {}\n Second: {}\n Third: {}\n Fourth: {}", + first_err, second_err, third_err, fourth_err, + ))) + } +} + +impl<'de, T, U> DeserializeAs<'de, T> for FromInto<U> +where + U: Into<T>, + U: Deserialize<'de>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + Ok(U::deserialize(deserializer)?.into()) + } +} + +impl<'de, T, U> DeserializeAs<'de, T> for TryFromInto<U> +where + U: TryInto<T>, + <U as TryInto<T>>::Error: Display, + U: Deserialize<'de>, +{ + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + { + U::deserialize(deserializer)? + .try_into() + .map_err(DeError::custom) + } +} + +#[cfg(feature = "alloc")] +impl<'de> DeserializeAs<'de, Cow<'de, str>> for BorrowCow { + fn deserialize_as<D>(deserializer: D) -> Result<Cow<'de, str>, D::Error> + where + D: Deserializer<'de>, + { + struct CowVisitor; + + impl<'de> Visitor<'de> for CowVisitor { + type Value = Cow<'de, str>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an optionally borrowed string") + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Borrowed(v)) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned(v.to_owned())) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(Cow::Owned(v)) + } + } + + deserializer.deserialize_string(CowVisitor) + } +} + +#[cfg(feature = "alloc")] +impl<'de> DeserializeAs<'de, Cow<'de, [u8]>> for BorrowCow { + fn deserialize_as<D>(deserializer: D) -> Result<Cow<'de, [u8]>, D::Error> + where + D: Deserializer<'de>, + { + Bytes::deserialize_as(deserializer) + } +} + +#[cfg(feature = "alloc")] +impl<'de, const N: usize> DeserializeAs<'de, Cow<'de, [u8; N]>> for BorrowCow { + fn deserialize_as<D>(deserializer: D) -> Result<Cow<'de, [u8; N]>, D::Error> + where + D: Deserializer<'de>, + { + Bytes::deserialize_as(deserializer) + } +} + +impl<'de> DeserializeAs<'de, bool> for BoolFromInt<Strict> { + fn deserialize_as<D>(deserializer: D) -> Result<bool, D::Error> + where + D: Deserializer<'de>, + { + struct U8Visitor; + impl<'de> Visitor<'de> for U8Visitor { + type Value = bool; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an integer 0 or 1") + } + + fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> + where + E: DeError, + { + match v { + 0 => Ok(false), + 1 => Ok(true), + unexp => Err(DeError::invalid_value( + Unexpected::Unsigned(unexp as u64), + &"0 or 1", + )), + } + } + + fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E> + where + E: DeError, + { + match v { + 0 => Ok(false), + 1 => Ok(true), + unexp => Err(DeError::invalid_value( + Unexpected::Signed(unexp as i64), + &"0 or 1", + )), + } + } + + fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> + where + E: DeError, + { + match v { + 0 => Ok(false), + 1 => Ok(true), + unexp => Err(DeError::invalid_value( + Unexpected::Unsigned(unexp), + &"0 or 1", + )), + } + } + + fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> + where + E: DeError, + { + match v { + 0 => Ok(false), + 1 => Ok(true), + unexp => Err(DeError::invalid_value(Unexpected::Signed(unexp), &"0 or 1")), + } + } + + fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> + where + E: DeError, + { + match v { + 0 => Ok(false), + 1 => Ok(true), + unexp => Err(DeError::invalid_value( + Unexpected::Unsigned(unexp as u64), + &"0 or 1", + )), + } + } + + fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> + where + E: DeError, + { + match v { + 0 => Ok(false), + 1 => Ok(true), + unexp => Err(DeError::invalid_value( + Unexpected::Signed(unexp as i64), + &"0 or 1", + )), + } + } + } + + deserializer.deserialize_u8(U8Visitor) + } +} + +impl<'de> DeserializeAs<'de, bool> for BoolFromInt<Flexible> { + fn deserialize_as<D>(deserializer: D) -> Result<bool, D::Error> + where + D: Deserializer<'de>, + { + struct U8Visitor; + impl<'de> Visitor<'de> for U8Visitor { + type Value = bool; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an integer") + } + + fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v != 0) + } + + fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v != 0) + } + + fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v != 0) + } + + fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v != 0) + } + + fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v != 0) + } + + fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> + where + E: DeError, + { + Ok(v != 0) + } + } + + deserializer.deserialize_u8(U8Visitor) + } +} + +// endregion diff --git a/third_party/rust/serde_with/src/de/mod.rs b/third_party/rust/serde_with/src/de/mod.rs new file mode 100644 index 0000000000..f9eb312498 --- /dev/null +++ b/third_party/rust/serde_with/src/de/mod.rs @@ -0,0 +1,158 @@ +//! Module for [`DeserializeAs`][] implementations +//! +//! The module contains the [`DeserializeAs`][] trait and helper code. +//! Additionally, it contains implementations of [`DeserializeAs`][] for types defined in the Rust Standard Library or this crate. +//! +//! You can find more details on how to implement this trait for your types in the documentation of the [`DeserializeAs`][] trait and details about the usage in the [user guide][]. +//! +//! [user guide]: crate::guide + +#[cfg(feature = "alloc")] +mod duplicates; +mod impls; + +use crate::prelude::*; + +/// A **data structure** that can be deserialized from any data format supported by Serde, analogue to [`Deserialize`]. +/// +/// The trait is analogue to the [`serde::Deserialize`][`Deserialize`] trait, with the same meaning of input and output arguments. +/// It can and should be implemented using the same code structure as the [`Deserialize`] trait. +/// As such, the same advice for [implementing `Deserialize`][impl-deserialize] applies here. +/// +/// # Differences to [`Deserialize`] +/// +/// The trait is only required for container-like types or types implementing specific conversion functions. +/// Container-like types are [`Vec`], [`BTreeMap`], but also [`Option`] and [`Box`]. +/// Conversion types deserialize into a different Rust type. +/// For example, [`DisplayFromStr`] uses the [`FromStr`] trait after deserializing a string and [`DurationSeconds`] creates a [`Duration`] from either String or integer values. +/// +/// This code shows how to implement [`Deserialize`] for [`Box`]: +/// +/// ```rust,ignore +/// impl<'de, T: Deserialize<'de>> Deserialize<'de> for Box<T> { +/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> +/// where +/// D: Deserializer<'de>, +/// { +/// Ok(Box::new(Deserialize::deserialize(deserializer)?)) +/// } +/// } +/// ``` +/// +/// and this code shows how to do the same using [`DeserializeAs`][]: +/// +/// ```rust,ignore +/// impl<'de, T, U> DeserializeAs<'de, Box<T>> for Box<U> +/// where +/// U: DeserializeAs<'de, T>, +/// { +/// fn deserialize_as<D>(deserializer: D) -> Result<Box<T>, D::Error> +/// where +/// D: Deserializer<'de>, +/// { +/// Ok(Box::new( +/// DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(), +/// )) +/// } +/// } +/// ``` +/// +/// It uses two type parameters, `T` and `U` instead of only one and performs the deserialization step using the `DeserializeAsWrap` type. +/// The `T` type is the on the Rust side after deserialization, whereas the `U` type determines how the value will be deserialized. +/// These two changes are usually enough to make a container type implement [`DeserializeAs`][]. +/// +/// +/// [`DeserializeAsWrap`] is a piece of glue code which turns [`DeserializeAs`] into a serde compatible datatype, by converting all calls to `deserialize` into `deserialize_as`. +/// This allows us to implement [`DeserializeAs`] such that it can be applied recursively throughout the whole data structure. +/// This is mostly important for container types, such as `Vec` or `BTreeMap`. +/// In a `BTreeMap` this allows us to specify two different serialization behaviors, one for key and one for value, using the [`DeserializeAs`] trait. +/// +/// ## Implementing a converter Type +/// +/// This shows a simplified implementation for [`DisplayFromStr`]. +/// +/// ```rust +/// # #[cfg(all(feature = "macros"))] { +/// # use serde::Deserialize; +/// # use serde::de::Error; +/// # use serde_with::{serde_as, DeserializeAs}; +/// # use std::str::FromStr; +/// # use std::fmt::Display; +/// struct DisplayFromStr; +/// +/// impl<'de, T> DeserializeAs<'de, T> for DisplayFromStr +/// where +/// T: FromStr, +/// T::Err: Display, +/// { +/// fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> +/// where +/// D: serde::Deserializer<'de>, +/// { +/// let s = String::deserialize(deserializer).map_err(Error::custom)?; +/// s.parse().map_err(Error::custom) +/// } +/// } +/// # +/// # #[serde_as] +/// # #[derive(serde::Deserialize)] +/// # struct S (#[serde_as(as = "DisplayFromStr")] bool); +/// # +/// # assert_eq!(false, serde_json::from_str::<S>(r#""false""#).unwrap().0); +/// # } +/// ``` +/// [`Box`]: std::boxed::Box +/// [`BTreeMap`]: std::collections::BTreeMap +/// [`Duration`]: std::time::Duration +/// [`FromStr`]: std::str::FromStr +/// [`Vec`]: std::vec::Vec +/// [impl-deserialize]: https://serde.rs/impl-deserialize.html +pub trait DeserializeAs<'de, T>: Sized { + /// Deserialize this value from the given Serde deserializer. + fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>; +} + +/// Helper type to implement [`DeserializeAs`] for container-like types. +pub struct DeserializeAsWrap<T, U> { + value: T, + marker: PhantomData<U>, +} + +impl<T, U> DeserializeAsWrap<T, U> { + /// Return the inner value of type `T`. + pub fn into_inner(self) -> T { + self.value + } +} + +impl<'de, T, U> Deserialize<'de> for DeserializeAsWrap<T, U> +where + U: DeserializeAs<'de, T>, +{ + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + U::deserialize_as(deserializer).map(|value| Self { + value, + marker: PhantomData, + }) + } +} + +impl<T: ?Sized> As<T> { + /// Deserialize type `T` using [`DeserializeAs`][] + /// + /// The function signature is compatible with [serde's with-annotation][with-annotation]. + /// + /// [with-annotation]: https://serde.rs/field-attrs.html#with + pub fn deserialize<'de, D, I>(deserializer: D) -> Result<I, D::Error> + where + T: DeserializeAs<'de, I>, + D: Deserializer<'de>, + { + T::deserialize_as(deserializer) + } +} |