summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_with/src/de
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/serde_with/src/de
parentInitial commit. (diff)
downloadfirefox-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.rs223
-rw-r--r--third_party/rust/serde_with/src/de/impls.rs1937
-rw-r--r--third_party/rust/serde_with/src/de/mod.rs158
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)
+ }
+}