From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../rust/serde_with/src/ser/const_arrays.rs | 90 +++ third_party/rust/serde_with/src/ser/impls.rs | 739 +++++++++++++++++++++ .../rust/serde_with/src/ser/legacy_arrays.rs | 34 + third_party/rust/serde_with/src/ser/mod.rs | 158 +++++ 4 files changed, 1021 insertions(+) create mode 100644 third_party/rust/serde_with/src/ser/const_arrays.rs create mode 100644 third_party/rust/serde_with/src/ser/impls.rs create mode 100644 third_party/rust/serde_with/src/ser/legacy_arrays.rs create mode 100644 third_party/rust/serde_with/src/ser/mod.rs (limited to 'third_party/rust/serde_with/src/ser') 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 SerializeAs<[T; N]> for [As; N] +where + As: SerializeAs, +{ + fn serialize_as(array: &[T; N], serializer: S) -> Result + where + S: Serializer, + { + use serde::ser::SerializeTuple; + let mut arr = serializer.serialize_tuple(N)?; + for elem in array { + arr.serialize_element(&SerializeAsWrap::::new(elem))?; + } + arr.end() + } +} + +macro_rules! tuple_seq_as_map_impl_intern { + ($tyorig:ty, $ty:ident ) => { + #[allow(clippy::implicit_hasher)] + impl SerializeAs<$tyorig> for $ty + where + KAs: SerializeAs, + VAs: SerializeAs, + { + fn serialize_as(source: &$tyorig, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_map(source.iter().map(|(k, v)| { + ( + SerializeAsWrap::::new(k), + SerializeAsWrap::::new(v), + ) + })) + } + } + }; +} +tuple_seq_as_map_impl_intern!([(K, V); N], BTreeMap); +tuple_seq_as_map_impl_intern!([(K, V); N], HashMap); + +impl SerializeAs<[u8; N]> for Bytes { + fn serialize_as(bytes: &[u8; N], serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl SerializeAs<&[u8; N]> for Bytes { + fn serialize_as(bytes: &&[u8; N], serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(*bytes) + } +} + +impl SerializeAs> for Bytes { + fn serialize_as(bytes: &Box<[u8; N]>, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(&**bytes) + } +} + +impl<'a, const N: usize> SerializeAs> for Bytes { + fn serialize_as(bytes: &Cow<'a, [u8; N]>, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes.as_ref()) + } +} + +impl<'a, const N: usize> SerializeAs> for BorrowCow { + fn serialize_as(value: &Cow<'a, [u8; N]>, serializer: S) -> Result + 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: ?Sized, + U: ?Sized, +{ + fn serialize_as(source: &&'a T, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl<'a, T, U> SerializeAs<&'a mut T> for &'a mut U +where + U: SerializeAs, + T: ?Sized, + U: ?Sized, +{ + fn serialize_as(source: &&'a mut T, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs> for Box +where + U: SerializeAs, +{ + fn serialize_as(source: &Box, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs> for Option +where + U: SerializeAs, +{ + fn serialize_as(source: &Option, serializer: S) -> Result + where + S: Serializer, + { + match *source { + Some(ref value) => serializer.serialize_some(&SerializeAsWrap::::new(value)), + None => serializer.serialize_none(), + } + } +} + +impl SerializeAs> for Rc +where + U: SerializeAs, +{ + fn serialize_as(source: &Rc, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs> for RcWeak +where + U: SerializeAs, +{ + fn serialize_as(source: &RcWeak, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::>, Option>>::new(&source.upgrade()) + .serialize(serializer) + } +} + +impl SerializeAs> for Arc +where + U: SerializeAs, +{ + fn serialize_as(source: &Arc, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs> for ArcWeak +where + U: SerializeAs, +{ + fn serialize_as(source: &ArcWeak, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::>, Option>>::new(&source.upgrade()) + .serialize(serializer) + } +} + +impl SerializeAs> for Cell +where + U: SerializeAs, + T: Copy, +{ + fn serialize_as(source: &Cell, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(&source.get()).serialize(serializer) + } +} + +impl SerializeAs> for RefCell +where + U: SerializeAs, +{ + fn serialize_as(source: &RefCell, serializer: S) -> Result + where + S: Serializer, + { + match source.try_borrow() { + Ok(source) => SerializeAsWrap::::new(&*source).serialize(serializer), + Err(_) => Err(S::Error::custom("already mutably borrowed")), + } + } +} + +impl SerializeAs> for Mutex +where + U: SerializeAs, +{ + fn serialize_as(source: &Mutex, serializer: S) -> Result + where + S: Serializer, + { + match source.lock() { + Ok(source) => SerializeAsWrap::::new(&*source).serialize(serializer), + Err(_) => Err(S::Error::custom("lock poison error while serializing")), + } + } +} + +impl SerializeAs> for RwLock +where + U: SerializeAs, +{ + fn serialize_as(source: &RwLock, serializer: S) -> Result + where + S: Serializer, + { + match source.read() { + Ok(source) => SerializeAsWrap::::new(&*source).serialize(serializer), + Err(_) => Err(S::Error::custom("lock poison error while serializing")), + } + } +} + +impl SerializeAs> for Result +where + TAs: SerializeAs, + EAs: SerializeAs, +{ + fn serialize_as(source: &Result, serializer: S) -> Result + where + S: Serializer, + { + source + .as_ref() + .map(SerializeAsWrap::::new) + .map_err(SerializeAsWrap::::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 SerializeAs<$ty> for $ty + where + U: SerializeAs, + $(T: ?Sized + $tbound1 $(+ $tbound2)*,)* + $($typaram: ?Sized + $bound,)* + { + fn serialize_as(source: &$ty, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::::new(item))) + } + } + } +} + +type BoxedSlice = Box<[T]>; +type Slice = [T]; +seq_impl!(BinaryHeap); +seq_impl!(BoxedSlice); +seq_impl!(BTreeSet); +seq_impl!(HashSet); +seq_impl!(LinkedList); +seq_impl!(Slice); +seq_impl!(Vec); +seq_impl!(VecDeque); +#[cfg(feature = "indexmap")] +seq_impl!(IndexSet); + +macro_rules! map_impl { + ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { + impl SerializeAs<$ty> for $ty + where + KU: SerializeAs, + VU: SerializeAs, + $(K: ?Sized + $kbound1 $(+ $kbound2)*,)* + $($typaram: ?Sized + $bound,)* + { + fn serialize_as(source: &$ty, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_map(source.iter().map(|(k, v)| (SerializeAsWrap::::new(k), SerializeAsWrap::::new(v)))) + } + } + } +} + +map_impl!(BTreeMap); +map_impl!(HashMap); +#[cfg(feature = "indexmap")] +map_impl!(IndexMap); + +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(tuple: &($($t,)+), serializer: S) -> Result + 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 SerializeAs<$ty> for Vec<(KAs, VAs)> + where + KAs: SerializeAs, + VAs: SerializeAs, + { + fn serialize_as(source: &$ty, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq(source.iter().map(|(k, v)| { + ( + SerializeAsWrap::::new(k), + SerializeAsWrap::::new(v), + ) + })) + } + } + }; +} +map_as_tuple_seq!(BTreeMap); +// TODO HashMap with a custom hasher support would be better, but results in "unconstrained type parameter" +map_as_tuple_seq!(HashMap); +#[cfg(feature = "indexmap")] +map_as_tuple_seq!(IndexMap); + +// endregion +/////////////////////////////////////////////////////////////////////////////// +// region: Conversion types which cause different serialization behavior + +impl SerializeAs for Same +where + T: Serialize + ?Sized, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + source.serialize(serializer) + } +} + +impl SerializeAs for DisplayFromStr +where + T: Display, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + crate::rust::display_fromstr::serialize(source, serializer) + } +} + +impl SerializeAs> for VecSkipError +where + U: SerializeAs, +{ + fn serialize_as(source: &Vec, serializer: S) -> Result + where + S: Serializer, + { + Vec::::serialize_as(source, serializer) + } +} + +impl SerializeAs> for NoneAsEmptyString +where + AsRefStr: AsRef, +{ + fn serialize_as(source: &Option, serializer: S) -> Result + where + S: Serializer, + { + crate::rust::string_empty_as_none::serialize(source, serializer) + } +} + +macro_rules! tuple_seq_as_map_impl_intern { + ($tyorig:ty, $ty:ident ) => { + #[allow(clippy::implicit_hasher)] + impl SerializeAs<$tyorig> for $ty + where + KAs: SerializeAs, + VAs: SerializeAs, + { + fn serialize_as(source: &$tyorig, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_map(source.iter().map(|(k, v)| { + ( + SerializeAsWrap::::new(k), + SerializeAsWrap::::new(v), + ) + })) + } + } + }; +} +macro_rules! tuple_seq_as_map_impl { + ($($ty:ty $(,)?)+) => {$( + tuple_seq_as_map_impl_intern!($ty, BTreeMap); + tuple_seq_as_map_impl_intern!($ty, HashMap); + )+} +} + +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 SerializeAs for DefaultOnError +where + TAs: SerializeAs, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + TAs::serialize_as(source, serializer) + } +} + +impl SerializeAs> for BytesOrString { + fn serialize_as(source: &Vec, serializer: S) -> Result + where + S: Serializer, + { + source.serialize(serializer) + } +} + +impl SerializeAs for StringWithSeparator +where + SEPARATOR: Separator, + for<'a> &'a I: IntoIterator, + T: ToString, +{ + fn serialize_as(source: &I, serializer: S) -> Result + 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(source: &$ty, serializer: S) -> Result + 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 SerializeAs for DefaultOnNull +where + U: SerializeAs, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_some(&SerializeAsWrap::::new(source)) + } +} + +impl SerializeAs<&[u8]> for Bytes { + fn serialize_as(bytes: &&[u8], serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl SerializeAs> for Bytes { + fn serialize_as(bytes: &Vec, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl SerializeAs> for Bytes { + fn serialize_as(bytes: &Box<[u8]>, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl<'a> SerializeAs> for Bytes { + fn serialize_as(bytes: &Cow<'a, [u8]>, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } +} + +impl SerializeAs> for OneOrMany +where + U: SerializeAs, +{ + fn serialize_as(source: &Vec, serializer: S) -> Result + where + S: Serializer, + { + match source.len() { + 1 => SerializeAsWrap::::new(source.iter().next().expect("Cannot be empty")) + .serialize(serializer), + _ => SerializeAsWrap::, Vec>::new(source).serialize(serializer), + } + } +} + +impl SerializeAs> for OneOrMany +where + U: SerializeAs, +{ + fn serialize_as(source: &Vec, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::, Vec>::new(source).serialize(serializer) + } +} + +impl SerializeAs for PickFirst<(TAs1,)> +where + TAs1: SerializeAs, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs for PickFirst<(TAs1, TAs2)> +where + TAs1: SerializeAs, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs for PickFirst<(TAs1, TAs2, TAs3)> +where + TAs1: SerializeAs, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs for PickFirst<(TAs1, TAs2, TAs3, TAs4)> +where + TAs1: SerializeAs, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + SerializeAsWrap::::new(source).serialize(serializer) + } +} + +impl SerializeAs for FromInto +where + T: Into + Clone, + U: Serialize, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + source.clone().into().serialize(serializer) + } +} + +impl SerializeAs for TryFromInto +where + T: TryInto + Clone, + >::Error: Display, + U: Serialize, +{ + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + source + .clone() + .try_into() + .map_err(S::Error::custom)? + .serialize(serializer) + } +} + +impl<'a> SerializeAs> for BorrowCow { + fn serialize_as(source: &Cow<'a, str>, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(source) + } +} + +impl<'a> SerializeAs> for BorrowCow { + fn serialize_as(value: &Cow<'a, [u8]>, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq(value.iter()) + } +} + +impl SerializeAs for BoolFromInt { + fn serialize_as(source: &bool, serializer: S) -> Result + 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 SerializeAs<[T; $len]> for [As; $len] + where + As: SerializeAs, + { + fn serialize_as(array: &[T; $len], serializer: S) -> Result + where + S: Serializer, + { + use serde::ser::SerializeTuple; + let mut arr = serializer.serialize_tuple($len)?; + for elem in array { + arr.serialize_element(&SerializeAsWrap::::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 Serialize for Box +/// where +/// T: Serialize, +/// { +/// #[inline] +/// fn serialize(&self, serializer: S) -> Result +/// where +/// S: Serializer, +/// { +/// (**self).serialize(serializer) +/// } +/// } +/// ``` +/// +/// and this code shows how to do the same using [`SerializeAs`][]: +/// +/// ```rust,ignore +/// impl SerializeAs> for Box +/// where +/// U: SerializeAs, +/// { +/// fn serialize_as(source: &Box, serializer: S) -> Result +/// where +/// S: Serializer, +/// { +/// SerializeAsWrap::::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 SerializeAs for DisplayFromStr +/// where +/// T: Display, +/// { +/// fn serialize_as(source: &T, serializer: S) -> Result +/// 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 { + /// Serialize this value into the given Serde serializer. + fn serialize_as(source: &T, serializer: S) -> Result + 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, +} + +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, +{ + fn serialize(&self, serializer: S) -> Result + 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, +{ + fn from(value: &'a T) -> Self { + Self::new(value) + } +} -- cgit v1.2.3