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