diff options
Diffstat (limited to 'third_party/rust/serde_with/src/ser')
-rw-r--r-- | third_party/rust/serde_with/src/ser/const_arrays.rs | 90 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/ser/impls.rs | 739 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/ser/legacy_arrays.rs | 34 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/ser/mod.rs | 158 |
4 files changed, 1021 insertions, 0 deletions
diff --git a/third_party/rust/serde_with/src/ser/const_arrays.rs b/third_party/rust/serde_with/src/ser/const_arrays.rs new file mode 100644 index 0000000000..b864f2b7e5 --- /dev/null +++ b/third_party/rust/serde_with/src/ser/const_arrays.rs @@ -0,0 +1,90 @@ +use super::*; +use alloc::{borrow::Cow, boxed::Box, collections::BTreeMap}; +use std::collections::HashMap; + +impl<T, As, const N: usize> SerializeAs<[T; N]> for [As; N] +where + As: SerializeAs<T>, +{ + fn serialize_as<S>(array: &[T; N], serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + use serde::ser::SerializeTuple; + let mut arr = serializer.serialize_tuple(N)?; + for elem in array { + arr.serialize_element(&SerializeAsWrap::<T, As>::new(elem))?; + } + arr.end() + } +} + +macro_rules! tuple_seq_as_map_impl_intern { + ($tyorig:ty, $ty:ident <K, V>) => { + #[allow(clippy::implicit_hasher)] + impl<K, KAs, V, VAs, const N: usize> SerializeAs<$tyorig> for $ty<KAs, VAs> + where + KAs: SerializeAs<K>, + VAs: SerializeAs<V>, + { + fn serialize_as<S>(source: &$tyorig, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_map(source.iter().map(|(k, v)| { + ( + SerializeAsWrap::<K, KAs>::new(k), + SerializeAsWrap::<V, VAs>::new(v), + ) + })) + } + } + }; +} +tuple_seq_as_map_impl_intern!([(K, V); N], BTreeMap<K, V>); +tuple_seq_as_map_impl_intern!([(K, V); N], HashMap<K, V>); + +impl<const N: usize> SerializeAs<[u8; N]> for Bytes { + fn serialize_as<S>(bytes: &[u8; N], serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl<const N: usize> SerializeAs<&[u8; N]> for Bytes { + fn serialize_as<S>(bytes: &&[u8; N], serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(*bytes) + } +} + +impl<const N: usize> SerializeAs<Box<[u8; N]>> for Bytes { + fn serialize_as<S>(bytes: &Box<[u8; N]>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(&**bytes) + } +} + +impl<'a, const N: usize> SerializeAs<Cow<'a, [u8; N]>> for Bytes { + fn serialize_as<S>(bytes: &Cow<'a, [u8; N]>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(bytes.as_ref()) + } +} + +impl<'a, const N: usize> SerializeAs<Cow<'a, [u8; N]>> for BorrowCow { + fn serialize_as<S>(value: &Cow<'a, [u8; N]>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_seq(value.iter()) + } +} diff --git a/third_party/rust/serde_with/src/ser/impls.rs b/third_party/rust/serde_with/src/ser/impls.rs new file mode 100644 index 0000000000..16a8fb913c --- /dev/null +++ b/third_party/rust/serde_with/src/ser/impls.rs @@ -0,0 +1,739 @@ +use super::*; +use crate::{ + formats::Strictness, rust::StringWithSeparator, utils::duration::DurationSigned, Separator, +}; +use alloc::{ + borrow::Cow, + boxed::Box, + collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}, + rc::{Rc, Weak as RcWeak}, + string::{String, ToString}, + sync::{Arc, Weak as ArcWeak}, + vec::Vec, +}; +use core::{ + cell::{Cell, RefCell}, + convert::TryInto, + fmt::Display, + time::Duration, +}; +#[cfg(feature = "indexmap")] +use indexmap_crate::{IndexMap, IndexSet}; +use serde::ser::Error; +use std::{ + collections::{HashMap, HashSet}, + sync::{Mutex, RwLock}, + time::SystemTime, +}; + +/////////////////////////////////////////////////////////////////////////////// +// region: Simple Wrapper types (e.g., Box, Option) + +impl<'a, T, U> SerializeAs<&'a T> for &'a U +where + U: SerializeAs<T>, + T: ?Sized, + U: ?Sized, +{ + fn serialize_as<S>(source: &&'a T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, U>::new(source).serialize(serializer) + } +} + +impl<'a, T, U> SerializeAs<&'a mut T> for &'a mut U +where + U: SerializeAs<T>, + T: ?Sized, + U: ?Sized, +{ + fn serialize_as<S>(source: &&'a mut T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, U>::new(source).serialize(serializer) + } +} + +impl<T, U> SerializeAs<Box<T>> for Box<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Box<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, U>::new(source).serialize(serializer) + } +} + +impl<T, U> SerializeAs<Option<T>> for Option<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Option<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match *source { + Some(ref value) => serializer.serialize_some(&SerializeAsWrap::<T, U>::new(value)), + None => serializer.serialize_none(), + } + } +} + +impl<T, U> SerializeAs<Rc<T>> for Rc<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Rc<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, U>::new(source).serialize(serializer) + } +} + +impl<T, U> SerializeAs<RcWeak<T>> for RcWeak<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &RcWeak<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<Option<Rc<T>>, Option<Rc<U>>>::new(&source.upgrade()) + .serialize(serializer) + } +} + +impl<T, U> SerializeAs<Arc<T>> for Arc<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Arc<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, U>::new(source).serialize(serializer) + } +} + +impl<T, U> SerializeAs<ArcWeak<T>> for ArcWeak<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &ArcWeak<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<Option<Arc<T>>, Option<Arc<U>>>::new(&source.upgrade()) + .serialize(serializer) + } +} + +impl<T, U> SerializeAs<Cell<T>> for Cell<U> +where + U: SerializeAs<T>, + T: Copy, +{ + fn serialize_as<S>(source: &Cell<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, U>::new(&source.get()).serialize(serializer) + } +} + +impl<T, U> SerializeAs<RefCell<T>> for RefCell<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &RefCell<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match source.try_borrow() { + Ok(source) => SerializeAsWrap::<T, U>::new(&*source).serialize(serializer), + Err(_) => Err(S::Error::custom("already mutably borrowed")), + } + } +} + +impl<T, U> SerializeAs<Mutex<T>> for Mutex<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Mutex<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match source.lock() { + Ok(source) => SerializeAsWrap::<T, U>::new(&*source).serialize(serializer), + Err(_) => Err(S::Error::custom("lock poison error while serializing")), + } + } +} + +impl<T, U> SerializeAs<RwLock<T>> for RwLock<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &RwLock<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match source.read() { + Ok(source) => SerializeAsWrap::<T, U>::new(&*source).serialize(serializer), + Err(_) => Err(S::Error::custom("lock poison error while serializing")), + } + } +} + +impl<T, TAs, E, EAs> SerializeAs<Result<T, E>> for Result<TAs, EAs> +where + TAs: SerializeAs<T>, + EAs: SerializeAs<E>, +{ + fn serialize_as<S>(source: &Result<T, E>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + source + .as_ref() + .map(SerializeAsWrap::<T, TAs>::new) + .map_err(SerializeAsWrap::<E, EAs>::new) + .serialize(serializer) + } +} + +// endregion +/////////////////////////////////////////////////////////////////////////////// +// region: Collection Types (e.g., Maps, Sets, Vec) + +macro_rules! seq_impl { + ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident )* >) => { + impl<T, U $(, $typaram)*> SerializeAs<$ty<T $(, $typaram)*>> for $ty<U $(, $typaram)*> + where + U: SerializeAs<T>, + $(T: ?Sized + $tbound1 $(+ $tbound2)*,)* + $($typaram: ?Sized + $bound,)* + { + fn serialize_as<S>(source: &$ty<T $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::<T, U>::new(item))) + } + } + } +} + +type BoxedSlice<T> = Box<[T]>; +type Slice<T> = [T]; +seq_impl!(BinaryHeap<T>); +seq_impl!(BoxedSlice<T>); +seq_impl!(BTreeSet<T>); +seq_impl!(HashSet<T, H: Sized>); +seq_impl!(LinkedList<T>); +seq_impl!(Slice<T>); +seq_impl!(Vec<T>); +seq_impl!(VecDeque<T>); +#[cfg(feature = "indexmap")] +seq_impl!(IndexSet<T, H: Sized>); + +macro_rules! map_impl { + ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { + impl<K, KU, V, VU $(, $typaram)*> SerializeAs<$ty<K, V $(, $typaram)*>> for $ty<KU, VU $(, $typaram)*> + where + KU: SerializeAs<K>, + VU: SerializeAs<V>, + $(K: ?Sized + $kbound1 $(+ $kbound2)*,)* + $($typaram: ?Sized + $bound,)* + { + fn serialize_as<S>(source: &$ty<K, V $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_map(source.iter().map(|(k, v)| (SerializeAsWrap::<K, KU>::new(k), SerializeAsWrap::<V, VU>::new(v)))) + } + } + } +} + +map_impl!(BTreeMap<K, V>); +map_impl!(HashMap<K, V, H: Sized>); +#[cfg(feature = "indexmap")] +map_impl!(IndexMap<K, V, H: Sized>); + +macro_rules! tuple_impl { + ($len:literal $($n:tt $t:ident $tas:ident)+) => { + impl<$($t, $tas,)+> SerializeAs<($($t,)+)> for ($($tas,)+) + where + $($tas: SerializeAs<$t>,)+ + { + fn serialize_as<S>(tuple: &($($t,)+), serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + use serde::ser::SerializeTuple; + let mut tup = serializer.serialize_tuple($len)?; + $( + tup.serialize_element(&SerializeAsWrap::<$t, $tas>::new(&tuple.$n))?; + )+ + tup.end() + } + } + }; +} + +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); + +macro_rules! map_as_tuple_seq { + ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V >) => { + impl<K, KAs, V, VAs> SerializeAs<$ty<K, V>> for Vec<(KAs, VAs)> + where + KAs: SerializeAs<K>, + VAs: SerializeAs<V>, + { + fn serialize_as<S>(source: &$ty<K, V>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_seq(source.iter().map(|(k, v)| { + ( + SerializeAsWrap::<K, KAs>::new(k), + SerializeAsWrap::<V, VAs>::new(v), + ) + })) + } + } + }; +} +map_as_tuple_seq!(BTreeMap<K, V>); +// TODO HashMap with a custom hasher support would be better, but results in "unconstrained type parameter" +map_as_tuple_seq!(HashMap<K, V>); +#[cfg(feature = "indexmap")] +map_as_tuple_seq!(IndexMap<K, V>); + +// endregion +/////////////////////////////////////////////////////////////////////////////// +// region: Conversion types which cause different serialization behavior + +impl<T> SerializeAs<T> for Same +where + T: Serialize + ?Sized, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + source.serialize(serializer) + } +} + +impl<T> SerializeAs<T> for DisplayFromStr +where + T: Display, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + crate::rust::display_fromstr::serialize(source, serializer) + } +} + +impl<T, U> SerializeAs<Vec<T>> for VecSkipError<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + Vec::<U>::serialize_as(source, serializer) + } +} + +impl<AsRefStr> SerializeAs<Option<AsRefStr>> for NoneAsEmptyString +where + AsRefStr: AsRef<str>, +{ + fn serialize_as<S>(source: &Option<AsRefStr>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + crate::rust::string_empty_as_none::serialize(source, serializer) + } +} + +macro_rules! tuple_seq_as_map_impl_intern { + ($tyorig:ty, $ty:ident <K, V>) => { + #[allow(clippy::implicit_hasher)] + impl<K, KAs, V, VAs> SerializeAs<$tyorig> for $ty<KAs, VAs> + where + KAs: SerializeAs<K>, + VAs: SerializeAs<V>, + { + fn serialize_as<S>(source: &$tyorig, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_map(source.iter().map(|(k, v)| { + ( + SerializeAsWrap::<K, KAs>::new(k), + SerializeAsWrap::<V, VAs>::new(v), + ) + })) + } + } + }; +} +macro_rules! tuple_seq_as_map_impl { + ($($ty:ty $(,)?)+) => {$( + tuple_seq_as_map_impl_intern!($ty, BTreeMap<K, V>); + tuple_seq_as_map_impl_intern!($ty, HashMap<K, V>); + )+} +} + +tuple_seq_as_map_impl! { + BinaryHeap<(K, V)>, + BTreeSet<(K, V)>, + LinkedList<(K, V)>, + Option<(K, V)>, + Vec<(K, V)>, + VecDeque<(K, V)>, +} +tuple_seq_as_map_impl!(HashSet<(K, V)>); +#[cfg(feature = "indexmap")] +tuple_seq_as_map_impl!(IndexSet<(K, V)>); + +impl<T, TAs> SerializeAs<T> for DefaultOnError<TAs> +where + TAs: SerializeAs<T>, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + TAs::serialize_as(source, serializer) + } +} + +impl SerializeAs<Vec<u8>> for BytesOrString { + fn serialize_as<S>(source: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + source.serialize(serializer) + } +} + +impl<SEPARATOR, I, T> SerializeAs<I> for StringWithSeparator<SEPARATOR, T> +where + SEPARATOR: Separator, + for<'a> &'a I: IntoIterator<Item = &'a T>, + T: ToString, +{ + fn serialize_as<S>(source: &I, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + let mut s = String::new(); + for v in source { + s.push_str(&*v.to_string()); + s.push_str(SEPARATOR::separator()); + } + serializer.serialize_str(if !s.is_empty() { + // remove trailing separator if present + &s[..s.len() - SEPARATOR::separator().len()] + } else { + &s[..] + }) + } +} + +macro_rules! use_signed_duration { + ( + $main_trait:ident $internal_trait:ident => + { + $ty:ty => + $({ + $format:ty, $strictness:ty => + $($tbound:ident: $bound:ident $(,)?)* + })* + } + ) => { + $( + impl<$($tbound,)*> SerializeAs<$ty> for $main_trait<$format, $strictness> + where + $($tbound: $bound,)* + { + fn serialize_as<S>(source: &$ty, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + $internal_trait::<$format, $strictness>::serialize_as( + &DurationSigned::from(source), + serializer, + ) + } + } + )* + }; + ( + $( $main_trait:ident $internal_trait:ident, )+ => $rest:tt + ) => { + $( use_signed_duration!($main_trait $internal_trait => $rest); )+ + }; +} + +use_signed_duration!( + DurationSeconds DurationSeconds, + DurationMilliSeconds DurationMilliSeconds, + DurationMicroSeconds DurationMicroSeconds, + DurationNanoSeconds DurationNanoSeconds, + => { + Duration => + {u64, STRICTNESS => STRICTNESS: Strictness} + {f64, STRICTNESS => STRICTNESS: Strictness} + {String, STRICTNESS => STRICTNESS: Strictness} + } +); +use_signed_duration!( + DurationSecondsWithFrac DurationSecondsWithFrac, + DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac, + DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac, + DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac, + => { + Duration => + {f64, STRICTNESS => STRICTNESS: Strictness} + {String, STRICTNESS => STRICTNESS: Strictness} + } +); + +use_signed_duration!( + TimestampSeconds DurationSeconds, + TimestampMilliSeconds DurationMilliSeconds, + TimestampMicroSeconds DurationMicroSeconds, + TimestampNanoSeconds DurationNanoSeconds, + => { + SystemTime => + {i64, STRICTNESS => STRICTNESS: Strictness} + {f64, STRICTNESS => STRICTNESS: Strictness} + {String, STRICTNESS => STRICTNESS: Strictness} + } +); +use_signed_duration!( + TimestampSecondsWithFrac DurationSecondsWithFrac, + TimestampMilliSecondsWithFrac DurationMilliSecondsWithFrac, + TimestampMicroSecondsWithFrac DurationMicroSecondsWithFrac, + TimestampNanoSecondsWithFrac DurationNanoSecondsWithFrac, + => { + SystemTime => + {f64, STRICTNESS => STRICTNESS: Strictness} + {String, STRICTNESS => STRICTNESS: Strictness} + } +); + +impl<T, U> SerializeAs<T> for DefaultOnNull<U> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_some(&SerializeAsWrap::<T, U>::new(source)) + } +} + +impl SerializeAs<&[u8]> for Bytes { + fn serialize_as<S>(bytes: &&[u8], serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl SerializeAs<Vec<u8>> for Bytes { + fn serialize_as<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl SerializeAs<Box<[u8]>> for Bytes { + fn serialize_as<S>(bytes: &Box<[u8]>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl<'a> SerializeAs<Cow<'a, [u8]>> for Bytes { + fn serialize_as<S>(bytes: &Cow<'a, [u8]>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl<T, U> SerializeAs<Vec<T>> for OneOrMany<U, formats::PreferOne> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match source.len() { + 1 => SerializeAsWrap::<T, U>::new(source.iter().next().expect("Cannot be empty")) + .serialize(serializer), + _ => SerializeAsWrap::<Vec<T>, Vec<U>>::new(source).serialize(serializer), + } + } +} + +impl<T, U> SerializeAs<Vec<T>> for OneOrMany<U, formats::PreferMany> +where + U: SerializeAs<T>, +{ + fn serialize_as<S>(source: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<Vec<T>, Vec<U>>::new(source).serialize(serializer) + } +} + +impl<T, TAs1> SerializeAs<T> for PickFirst<(TAs1,)> +where + TAs1: SerializeAs<T>, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer) + } +} + +impl<T, TAs1, TAs2> SerializeAs<T> for PickFirst<(TAs1, TAs2)> +where + TAs1: SerializeAs<T>, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer) + } +} + +impl<T, TAs1, TAs2, TAs3> SerializeAs<T> for PickFirst<(TAs1, TAs2, TAs3)> +where + TAs1: SerializeAs<T>, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer) + } +} + +impl<T, TAs1, TAs2, TAs3, TAs4> SerializeAs<T> for PickFirst<(TAs1, TAs2, TAs3, TAs4)> +where + TAs1: SerializeAs<T>, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer) + } +} + +impl<T, U> SerializeAs<T> for FromInto<U> +where + T: Into<U> + Clone, + U: Serialize, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + source.clone().into().serialize(serializer) + } +} + +impl<T, U> SerializeAs<T> for TryFromInto<U> +where + T: TryInto<U> + Clone, + <T as TryInto<U>>::Error: Display, + U: Serialize, +{ + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + source + .clone() + .try_into() + .map_err(S::Error::custom)? + .serialize(serializer) + } +} + +impl<'a> SerializeAs<Cow<'a, str>> for BorrowCow { + fn serialize_as<S>(source: &Cow<'a, str>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_str(source) + } +} + +impl<'a> SerializeAs<Cow<'a, [u8]>> for BorrowCow { + fn serialize_as<S>(value: &Cow<'a, [u8]>, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.collect_seq(value.iter()) + } +} + +impl<STRICTNESS: Strictness> SerializeAs<bool> for BoolFromInt<STRICTNESS> { + fn serialize_as<S>(source: &bool, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_u8(*source as u8) + } +} + +// endregion diff --git a/third_party/rust/serde_with/src/ser/legacy_arrays.rs b/third_party/rust/serde_with/src/ser/legacy_arrays.rs new file mode 100644 index 0000000000..2c228ee640 --- /dev/null +++ b/third_party/rust/serde_with/src/ser/legacy_arrays.rs @@ -0,0 +1,34 @@ +use super::*; +use alloc::collections::BTreeMap; +use std::collections::HashMap; + +macro_rules! array_impl { + ($($len:literal)+) => {$( + impl<T, As> SerializeAs<[T; $len]> for [As; $len] + where + As: SerializeAs<T>, + { + fn serialize_as<S>(array: &[T; $len], serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + use serde::ser::SerializeTuple; + let mut arr = serializer.serialize_tuple($len)?; + for elem in array { + arr.serialize_element(&SerializeAsWrap::<T, As>::new(elem))?; + } + arr.end() + } + } + )+}; +} + +array_impl!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32); + +tuple_seq_as_map_impl! { + [(K, V); 0], [(K, V); 1], [(K, V); 2], [(K, V); 3], [(K, V); 4], [(K, V); 5], [(K, V); 6], + [(K, V); 7], [(K, V); 8], [(K, V); 9], [(K, V); 10], [(K, V); 11], [(K, V); 12], [(K, V); 13], + [(K, V); 14], [(K, V); 15], [(K, V); 16], [(K, V); 17], [(K, V); 18], [(K, V); 19], [(K, V); 20], + [(K, V); 21], [(K, V); 22], [(K, V); 23], [(K, V); 24], [(K, V); 25], [(K, V); 26], [(K, V); 27], + [(K, V); 28], [(K, V); 29], [(K, V); 30], [(K, V); 31], [(K, V); 32], +} diff --git a/third_party/rust/serde_with/src/ser/mod.rs b/third_party/rust/serde_with/src/ser/mod.rs new file mode 100644 index 0000000000..dda0891e89 --- /dev/null +++ b/third_party/rust/serde_with/src/ser/mod.rs @@ -0,0 +1,158 @@ +//! Module for [`SerializeAs`][] implementations +//! +//! The module contains the [`SerializeAs`][] trait and helper code. +//! Additionally, it contains implementations of [`SerializeAs`][] 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 [`SerializeAs`][] trait and details about the usage in the [user guide][]. +//! +//! [user guide]: crate::guide + +mod const_arrays; +#[macro_use] +mod impls; + +use super::*; + +/// A **data structure** that can be serialized into any data format supported by Serde, analogue to [`Serialize`]. +/// +/// The trait is analogue to the [`serde::Serialize`][`Serialize`] trait, with the same meaning of input and output arguments. +/// It can and should the implemented using the same code structure as the [`Serialize`] trait. +/// As such, the same advice for [implementing `Serialize`][impl-serialize] applies here. +/// +/// # Differences to [`Serialize`] +/// +/// 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 serialize into a different serde data type. +/// For example, [`DisplayFromStr`] uses the [`Display`] trait to serialize a String and [`DurationSeconds`] converts a [`Duration`] into either String or integer values. +/// +/// This code shows how to implement [`Serialize`] for [`Box`]: +/// +/// ```rust,ignore +/// impl<T> Serialize for Box<T> +/// where +/// T: Serialize, +/// { +/// #[inline] +/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> +/// where +/// S: Serializer, +/// { +/// (**self).serialize(serializer) +/// } +/// } +/// ``` +/// +/// and this code shows how to do the same using [`SerializeAs`][]: +/// +/// ```rust,ignore +/// impl<T, U> SerializeAs<Box<T>> for Box<U> +/// where +/// U: SerializeAs<T>, +/// { +/// fn serialize_as<S>(source: &Box<T>, serializer: S) -> Result<S::Ok, S::Error> +/// where +/// S: Serializer, +/// { +/// SerializeAsWrap::<T, U>::new(source).serialize(serializer) +/// } +/// } +/// ``` +/// +/// It uses two type parameters, `T` and `U` instead of only one and performs the serialization step using the `SerializeAsWrap` type. +/// The `T` type is the on the Rust side before serialization, whereas the `U` type determines how the value will be serialized. +/// These two changes are usually enough to make a container type implement [`SerializeAs`][]. +/// +/// [`SerializeAsWrap`] is a piece of glue code which turns [`SerializeAs`] into a serde compatible datatype, by converting all calls to `serialize` into `serialize_as`. +/// This allows us to implement [`SerializeAs`] 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 [`SerializeAs`] trait. +/// +/// ## Implementing a converter Type +/// +/// This shows a simplified implementation for [`DisplayFromStr`]. +/// +/// ```rust +/// # #[cfg(all(feature = "macros"))] { +/// # use serde_with::SerializeAs; +/// # use std::fmt::Display; +/// struct DisplayFromStr; +/// +/// impl<T> SerializeAs<T> for DisplayFromStr +/// where +/// T: Display, +/// { +/// fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> +/// where +/// S: serde::Serializer, +/// { +/// serializer.collect_str(&source) +/// } +/// } +/// # +/// # #[serde_with::serde_as] +/// # #[derive(serde::Serialize)] +/// # struct S (#[serde_as(as = "DisplayFromStr")] bool); +/// # +/// # assert_eq!(r#""false""#, serde_json::to_string(&S(false)).unwrap()); +/// # } +/// ``` +/// +/// [`Box`]: std::boxed::Box +/// [`BTreeMap`]: std::collections::BTreeMap +/// [`Display`]: std::fmt::Display +/// [`Duration`]: std::time::Duration +/// [`Vec`]: std::vec::Vec +/// [impl-serialize]: https://serde.rs/impl-serialize.html +pub trait SerializeAs<T: ?Sized> { + /// Serialize this value into the given Serde serializer. + fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer; +} + +/// Helper type to implement [`SerializeAs`] for container-like types. +#[derive(Debug)] +pub struct SerializeAsWrap<'a, T: ?Sized, U: ?Sized> { + value: &'a T, + marker: PhantomData<U>, +} + +impl<'a, T, U> SerializeAsWrap<'a, T, U> +where + T: ?Sized, + U: ?Sized, +{ + /// Create new instance with provided value. + pub fn new(value: &'a T) -> Self { + Self { + value, + marker: PhantomData, + } + } +} + +impl<'a, T, U> Serialize for SerializeAsWrap<'a, T, U> +where + T: ?Sized, + U: ?Sized, + U: SerializeAs<T>, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + U::serialize_as(self.value, serializer) + } +} + +impl<'a, T, U> From<&'a T> for SerializeAsWrap<'a, T, U> +where + T: ?Sized, + U: ?Sized, + U: SerializeAs<T>, +{ + fn from(value: &'a T) -> Self { + Self::new(value) + } +} |