Skip to main content

serde_with/ser/
impls.rs

1pub(crate) use self::macros::*;
2use crate::{formats::Strictness, prelude::*};
3#[cfg(feature = "hashbrown_0_14")]
4use hashbrown_0_14::{HashMap as HashbrownMap014, HashSet as HashbrownSet014};
5#[cfg(feature = "hashbrown_0_15")]
6use hashbrown_0_15::{HashMap as HashbrownMap015, HashSet as HashbrownSet015};
7#[cfg(feature = "hashbrown_0_16")]
8use hashbrown_0_16::{HashMap as HashbrownMap016, HashSet as HashbrownSet016};
9#[cfg(feature = "hashbrown_0_17")]
10use hashbrown_0_17::{HashMap as HashbrownMap017, HashSet as HashbrownSet017};
11#[cfg(feature = "indexmap_1")]
12use indexmap_1::{IndexMap, IndexSet};
13#[cfg(feature = "indexmap_2")]
14use indexmap_2::{IndexMap as IndexMap2, IndexSet as IndexSet2};
15#[cfg(feature = "smallvec_1")]
16use smallvec_1::SmallVec;
17
18///////////////////////////////////////////////////////////////////////////////
19// Helper macro used internally
20
21#[cfg(feature = "alloc")]
22type BoxedSlice<T> = Box<[T]>;
23type Slice<T> = [T];
24type Ref<'a, T> = &'a T;
25type RefMut<'a, T> = &'a mut T;
26
27pub(crate) mod macros {
28    // The unused_imports lint has false-positives around macros
29    // https://github.com/rust-lang/rust/issues/78894
30    #![allow(unused_imports)]
31
32    macro_rules! foreach_map {
33    ($m:ident) => {
34        #[cfg(feature = "alloc")]
35        $m!(BTreeMap<K, V>);
36        #[cfg(feature = "std")]
37        $m!(HashMap<K, V, H: Sized>);
38        #[cfg(feature = "hashbrown_0_14")]
39        $m!(HashbrownMap014<K, V, H: Sized>);
40        #[cfg(feature = "hashbrown_0_15")]
41        $m!(HashbrownMap015<K, V, H: Sized>);
42        #[cfg(feature = "hashbrown_0_16")]
43        $m!(HashbrownMap016<K, V, H: Sized>);
44        #[cfg(feature = "hashbrown_0_17")]
45        $m!(HashbrownMap017<K, V, H: Sized>);
46        #[cfg(feature = "indexmap_1")]
47        $m!(IndexMap<K, V, H: Sized>);
48        #[cfg(feature = "indexmap_2")]
49        $m!(IndexMap2<K, V, H: Sized>);
50    };
51}
52
53    macro_rules! foreach_set {
54    ($m:ident, $T:tt) => {
55        #[cfg(feature = "alloc")]
56        $m!(BTreeSet<$T>);
57        #[cfg(feature = "std")]
58        $m!(HashSet<$T, H: Sized>);
59        #[cfg(feature = "hashbrown_0_14")]
60        $m!(HashbrownSet014<$T, H: Sized>);
61        #[cfg(feature = "hashbrown_0_15")]
62        $m!(HashbrownSet015<$T, H: Sized>);
63        #[cfg(feature = "hashbrown_0_16")]
64        $m!(HashbrownSet016<$T, H: Sized>);
65        #[cfg(feature = "hashbrown_0_17")]
66        $m!(HashbrownSet017<$T, H: Sized>);
67        #[cfg(feature = "indexmap_1")]
68        $m!(IndexSet<$T, H: Sized>);
69        #[cfg(feature = "indexmap_2")]
70        $m!(IndexSet2<$T, H: Sized>);
71    };
72    ($m:ident) => {
73        foreach_set!($m, T);
74    };
75}
76
77    macro_rules! foreach_seq {
78        ($m:ident, $T:tt) => {
79            foreach_set!($m, $T);
80
81            $m!(Slice<$T>);
82
83            #[cfg(feature = "alloc")]
84            $m!(BinaryHeap<$T>);
85            #[cfg(feature = "alloc")]
86            $m!(BoxedSlice<$T>);
87            #[cfg(feature = "alloc")]
88            $m!(LinkedList<$T>);
89            #[cfg(feature = "alloc")]
90            $m!(Vec<$T>);
91            #[cfg(feature = "alloc")]
92            $m!(VecDeque<$T>);
93        };
94        ($m:
95            ident) => {
96            foreach_seq!($m, T);
97        };
98    }
99
100    // Make the macros available to the rest of the crate
101    pub(crate) use foreach_map;
102    pub(crate) use foreach_seq;
103    pub(crate) use foreach_set;
104}
105
106///////////////////////////////////////////////////////////////////////////////
107// region: Simple Wrapper types (e.g., Box, Option)
108
109#[allow(unused_macros)]
110macro_rules! pinned_wrapper {
111    ($wrapper:ident $($lifetime:lifetime)?) => {
112        impl<$($lifetime,)? T, U> SerializeAs<Pin<$wrapper<$($lifetime,)? T>>> for Pin<$wrapper<$($lifetime,)? U>>
113        where
114            U: SerializeAs<T>,
115        {
116            fn serialize_as<S>(source: &Pin<$wrapper<$($lifetime,)? T>>, serializer: S) -> Result<S::Ok, S::Error>
117            where
118                S: Serializer,
119            {
120                SerializeAsWrap::<T, U>::new(source).serialize(serializer)
121            }
122        }
123    };
124}
125
126impl<'a, T, U> SerializeAs<&'a T> for &'a U
127where
128    U: SerializeAs<T>,
129    T: ?Sized,
130    U: ?Sized,
131{
132    fn serialize_as<S>(source: &&'a T, serializer: S) -> Result<S::Ok, S::Error>
133    where
134        S: Serializer,
135    {
136        SerializeAsWrap::<T, U>::new(source).serialize(serializer)
137    }
138}
139
140impl<'a, T, U> SerializeAs<&'a mut T> for &'a mut U
141where
142    U: SerializeAs<T>,
143    T: ?Sized,
144    U: ?Sized,
145{
146    fn serialize_as<S>(source: &&'a mut T, serializer: S) -> Result<S::Ok, S::Error>
147    where
148        S: Serializer,
149    {
150        SerializeAsWrap::<T, U>::new(source).serialize(serializer)
151    }
152}
153
154pinned_wrapper!(Ref 'a);
155pinned_wrapper!(RefMut 'a);
156
157#[cfg(feature = "alloc")]
158impl<T, U> SerializeAs<Box<T>> for Box<U>
159where
160    U: SerializeAs<T>,
161{
162    fn serialize_as<S>(source: &Box<T>, serializer: S) -> Result<S::Ok, S::Error>
163    where
164        S: Serializer,
165    {
166        SerializeAsWrap::<T, U>::new(source).serialize(serializer)
167    }
168}
169
170#[cfg(feature = "alloc")]
171pinned_wrapper!(Box);
172
173impl<T, U> SerializeAs<Option<T>> for Option<U>
174where
175    U: SerializeAs<T>,
176{
177    fn serialize_as<S>(source: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
178    where
179        S: Serializer,
180    {
181        match *source {
182            Some(ref value) => serializer.serialize_some(&SerializeAsWrap::<T, U>::new(value)),
183            None => serializer.serialize_none(),
184        }
185    }
186}
187
188impl<T, U> SerializeAs<Bound<T>> for Bound<U>
189where
190    U: SerializeAs<T>,
191    T: Sized,
192{
193    fn serialize_as<S>(source: &Bound<T>, serializer: S) -> Result<S::Ok, S::Error>
194    where
195        S: Serializer,
196    {
197        match source {
198            Bound::Unbounded => Bound::Unbounded,
199            Bound::Included(v) => Bound::Included(SerializeAsWrap::<T, U>::new(v)),
200            Bound::Excluded(v) => Bound::Excluded(SerializeAsWrap::<T, U>::new(v)),
201        }
202        .serialize(serializer)
203    }
204}
205
206#[cfg(feature = "alloc")]
207impl<T, U> SerializeAs<Rc<T>> for Rc<U>
208where
209    U: SerializeAs<T>,
210{
211    fn serialize_as<S>(source: &Rc<T>, serializer: S) -> Result<S::Ok, S::Error>
212    where
213        S: Serializer,
214    {
215        SerializeAsWrap::<T, U>::new(source).serialize(serializer)
216    }
217}
218
219#[cfg(feature = "alloc")]
220pinned_wrapper!(Rc);
221
222#[cfg(feature = "alloc")]
223impl<T, U> SerializeAs<RcWeak<T>> for RcWeak<U>
224where
225    U: SerializeAs<T>,
226{
227    fn serialize_as<S>(source: &RcWeak<T>, serializer: S) -> Result<S::Ok, S::Error>
228    where
229        S: Serializer,
230    {
231        SerializeAsWrap::<Option<Rc<T>>, Option<Rc<U>>>::new(&source.upgrade())
232            .serialize(serializer)
233    }
234}
235
236#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
237impl<T, U> SerializeAs<Arc<T>> for Arc<U>
238where
239    U: SerializeAs<T>,
240{
241    fn serialize_as<S>(source: &Arc<T>, serializer: S) -> Result<S::Ok, S::Error>
242    where
243        S: Serializer,
244    {
245        SerializeAsWrap::<T, U>::new(source).serialize(serializer)
246    }
247}
248
249#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
250pinned_wrapper!(Arc);
251
252#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
253impl<T, U> SerializeAs<ArcWeak<T>> for ArcWeak<U>
254where
255    U: SerializeAs<T>,
256{
257    fn serialize_as<S>(source: &ArcWeak<T>, serializer: S) -> Result<S::Ok, S::Error>
258    where
259        S: Serializer,
260    {
261        SerializeAsWrap::<Option<Arc<T>>, Option<Arc<U>>>::new(&source.upgrade())
262            .serialize(serializer)
263    }
264}
265
266impl<T, U> SerializeAs<Cell<T>> for Cell<U>
267where
268    U: SerializeAs<T>,
269    T: Copy,
270{
271    fn serialize_as<S>(source: &Cell<T>, serializer: S) -> Result<S::Ok, S::Error>
272    where
273        S: Serializer,
274    {
275        SerializeAsWrap::<T, U>::new(&source.get()).serialize(serializer)
276    }
277}
278
279impl<T, U> SerializeAs<RefCell<T>> for RefCell<U>
280where
281    U: SerializeAs<T>,
282{
283    fn serialize_as<S>(source: &RefCell<T>, serializer: S) -> Result<S::Ok, S::Error>
284    where
285        S: Serializer,
286    {
287        match source.try_borrow() {
288            Ok(source) => SerializeAsWrap::<T, U>::new(&*source).serialize(serializer),
289            Err(_) => Err(S::Error::custom("already mutably borrowed")),
290        }
291    }
292}
293
294#[cfg(feature = "std")]
295impl<T, U> SerializeAs<Mutex<T>> for Mutex<U>
296where
297    U: SerializeAs<T>,
298{
299    fn serialize_as<S>(source: &Mutex<T>, serializer: S) -> Result<S::Ok, S::Error>
300    where
301        S: Serializer,
302    {
303        match source.lock() {
304            Ok(source) => SerializeAsWrap::<T, U>::new(&*source).serialize(serializer),
305            Err(_) => Err(S::Error::custom("lock poison error while serializing")),
306        }
307    }
308}
309
310#[cfg(feature = "std")]
311impl<T, U> SerializeAs<RwLock<T>> for RwLock<U>
312where
313    U: SerializeAs<T>,
314{
315    fn serialize_as<S>(source: &RwLock<T>, serializer: S) -> Result<S::Ok, S::Error>
316    where
317        S: Serializer,
318    {
319        match source.read() {
320            Ok(source) => SerializeAsWrap::<T, U>::new(&*source).serialize(serializer),
321            Err(_) => Err(S::Error::custom("lock poison error while serializing")),
322        }
323    }
324}
325
326impl<T, TAs, E, EAs> SerializeAs<Result<T, E>> for Result<TAs, EAs>
327where
328    TAs: SerializeAs<T>,
329    EAs: SerializeAs<E>,
330{
331    fn serialize_as<S>(source: &Result<T, E>, serializer: S) -> Result<S::Ok, S::Error>
332    where
333        S: Serializer,
334    {
335        source
336            .as_ref()
337            .map(SerializeAsWrap::<T, TAs>::new)
338            .map_err(SerializeAsWrap::<E, EAs>::new)
339            .serialize(serializer)
340    }
341}
342
343impl<T, As, const N: usize> SerializeAs<[T; N]> for [As; N]
344where
345    As: SerializeAs<T>,
346{
347    fn serialize_as<S>(array: &[T; N], serializer: S) -> Result<S::Ok, S::Error>
348    where
349        S: Serializer,
350    {
351        let mut arr = serializer.serialize_tuple(N)?;
352        for elem in array {
353            arr.serialize_element(&SerializeAsWrap::<T, As>::new(elem))?;
354        }
355        arr.end()
356    }
357}
358
359// endregion
360///////////////////////////////////////////////////////////////////////////////
361// region: More complex wrappers that are not just a single value
362
363impl<Idx, IdxAs> SerializeAs<Range<Idx>> for Range<IdxAs>
364where
365    IdxAs: SerializeAs<Idx>,
366{
367    fn serialize_as<S>(value: &Range<Idx>, serializer: S) -> Result<S::Ok, S::Error>
368    where
369        S: Serializer,
370    {
371        Range {
372            start: SerializeAsWrap::<Idx, IdxAs>::new(&value.start),
373            end: SerializeAsWrap::<Idx, IdxAs>::new(&value.end),
374        }
375        .serialize(serializer)
376    }
377}
378
379impl<Idx, IdxAs> SerializeAs<RangeFrom<Idx>> for RangeFrom<IdxAs>
380where
381    IdxAs: SerializeAs<Idx>,
382{
383    fn serialize_as<S>(value: &RangeFrom<Idx>, serializer: S) -> Result<S::Ok, S::Error>
384    where
385        S: Serializer,
386    {
387        RangeFrom {
388            start: SerializeAsWrap::<Idx, IdxAs>::new(&value.start),
389        }
390        .serialize(serializer)
391    }
392}
393
394impl<Idx, IdxAs> SerializeAs<RangeInclusive<Idx>> for RangeInclusive<IdxAs>
395where
396    IdxAs: SerializeAs<Idx>,
397{
398    fn serialize_as<S>(value: &RangeInclusive<Idx>, serializer: S) -> Result<S::Ok, S::Error>
399    where
400        S: Serializer,
401    {
402        RangeInclusive::new(
403            SerializeAsWrap::<Idx, IdxAs>::new(value.start()),
404            SerializeAsWrap::<Idx, IdxAs>::new(value.end()),
405        )
406        .serialize(serializer)
407    }
408}
409
410impl<Idx, IdxAs> SerializeAs<RangeTo<Idx>> for RangeTo<IdxAs>
411where
412    IdxAs: SerializeAs<Idx>,
413{
414    fn serialize_as<S>(value: &RangeTo<Idx>, serializer: S) -> Result<S::Ok, S::Error>
415    where
416        S: Serializer,
417    {
418        RangeTo {
419            end: SerializeAsWrap::<Idx, IdxAs>::new(&value.end),
420        }
421        .serialize(serializer)
422    }
423}
424
425// endregion
426///////////////////////////////////////////////////////////////////////////////
427// region: Collection Types (e.g., Maps, Sets, Vec)
428
429macro_rules! seq_impl {
430    ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident )* >) => {
431        impl<T, U $(, $typaram)*> SerializeAs<$ty<T $(, $typaram)*>> for $ty<U $(, $typaram)*>
432        where
433            U: SerializeAs<T>,
434            $(T: ?Sized + $tbound1 $(+ $tbound2)*,)*
435            $($typaram: ?Sized + $bound,)*
436        {
437            fn serialize_as<S>(source: &$ty<T $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
438            where
439                S: Serializer,
440            {
441                serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::<T, U>::new(item)))
442            }
443        }
444    }
445}
446foreach_seq!(seq_impl);
447
448// SmallVec implementation
449#[cfg(feature = "smallvec_1")]
450impl<A, B> SerializeAs<SmallVec<A>> for SmallVec<B>
451where
452    A: smallvec_1::Array,
453    B: smallvec_1::Array,
454    B::Item: SerializeAs<A::Item>,
455{
456    fn serialize_as<S>(source: &SmallVec<A>, serializer: S) -> Result<S::Ok, S::Error>
457    where
458        S: Serializer,
459    {
460        serializer.collect_seq(source.iter().map(SerializeAsWrap::<A::Item, B::Item>::new))
461    }
462}
463
464#[cfg(feature = "alloc")]
465macro_rules! map_impl {
466    ($ty:ident < K, V $(, $typaram:ident : $bound:ident)* >) => {
467        impl<K, KU, V, VU $(, $typaram)*> SerializeAs<$ty<K, V $(, $typaram)*>> for $ty<KU, VU $(, $typaram)*>
468        where
469            KU: SerializeAs<K>,
470            VU: SerializeAs<V>,
471            $($typaram: ?Sized + $bound,)*
472        {
473            fn serialize_as<S>(source: &$ty<K, V $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
474            where
475                S: Serializer,
476            {
477                serializer.collect_map(source.iter().map(|(k, v)| (SerializeAsWrap::<K, KU>::new(k), SerializeAsWrap::<V, VU>::new(v))))
478            }
479        }
480    }
481}
482foreach_map!(map_impl);
483
484macro_rules! tuple_impl {
485    ($len:literal $($n:tt $t:ident $tas:ident)+) => {
486        impl<$($t, $tas,)+> SerializeAs<($($t,)+)> for ($($tas,)+)
487        where
488            $($tas: SerializeAs<$t>,)+
489        {
490            fn serialize_as<S>(tuple: &($($t,)+), serializer: S) -> Result<S::Ok, S::Error>
491            where
492                S: Serializer,
493            {
494                let mut tup = serializer.serialize_tuple($len)?;
495                $(
496                    tup.serialize_element(&SerializeAsWrap::<$t, $tas>::new(&tuple.$n))?;
497                )+
498                tup.end()
499            }
500        }
501    };
502}
503
504tuple_impl!(1 0 T0 As0);
505tuple_impl!(2 0 T0 As0 1 T1 As1);
506tuple_impl!(3 0 T0 As0 1 T1 As1 2 T2 As2);
507tuple_impl!(4 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3);
508tuple_impl!(5 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4);
509tuple_impl!(6 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5);
510tuple_impl!(7 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6);
511tuple_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);
512tuple_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);
513tuple_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);
514tuple_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);
515tuple_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);
516tuple_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);
517tuple_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);
518tuple_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);
519tuple_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);
520
521#[cfg(feature = "alloc")]
522macro_rules! map_as_tuple_seq_intern {
523    ($tyorig:ident < K, V $(, $typaram:ident : $bound:ident)* >, $ty:ident <(K, V)>) => {
524        impl<K, KAs, V, VAs $(, $typaram)*> SerializeAs<$tyorig<K, V $(, $typaram)*>> for $ty<(KAs, VAs)>
525        where
526            KAs: SerializeAs<K>,
527            VAs: SerializeAs<V>,
528            $($typaram: ?Sized + $bound,)*
529        {
530            fn serialize_as<S>(source: &$tyorig<K, V $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
531            where
532                S: Serializer,
533            {
534                serializer.collect_seq(source.iter().map(|(k, v)| {
535                    (
536                        SerializeAsWrap::<K, KAs>::new(k),
537                        SerializeAsWrap::<V, VAs>::new(v),
538                    )
539                }))
540            }
541        }
542    };
543}
544#[cfg(feature = "alloc")]
545macro_rules! map_as_tuple_seq {
546    ($tyorig:ident < K, V $(, $typaram:ident : $bound:ident)* >) => {
547        map_as_tuple_seq_intern!($tyorig<K, V $(, $typaram: $bound)* >, Seq<(K, V)>);
548        #[cfg(feature = "alloc")]
549        map_as_tuple_seq_intern!($tyorig<K, V $(, $typaram: $bound)* >, Vec<(K, V)>);
550    }
551}
552foreach_map!(map_as_tuple_seq);
553
554macro_rules! tuple_seq_as_map_impl_intern {
555    ($tyorig:ident < (K, V) $(, $typaram:ident : $bound:ident)* >, $ty:ident <K, V>) => {
556        #[allow(clippy::implicit_hasher)]
557        impl<K, KAs, V, VAs $(, $typaram)*> SerializeAs<$tyorig<(K, V) $(, $typaram)*>> for $ty<KAs, VAs>
558        where
559            KAs: SerializeAs<K>,
560            VAs: SerializeAs<V>,
561            $($typaram: ?Sized + $bound,)*
562        {
563            fn serialize_as<S>(source: &$tyorig<(K, V) $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
564            where
565                S: Serializer,
566            {
567                serializer.collect_map(source.iter().map(|(k, v)| {
568                    (
569                        SerializeAsWrap::<K, KAs>::new(k),
570                        SerializeAsWrap::<V, VAs>::new(v),
571                    )
572                }))
573            }
574        }
575    };
576}
577macro_rules! tuple_seq_as_map_impl {
578    ($tyorig:ident < (K, V) $(, $typaram:ident : $bound:ident)* >) => {
579        tuple_seq_as_map_impl_intern!($tyorig<(K, V) $(, $typaram: $bound)* >, Map<K, V>);
580        #[cfg(feature = "alloc")]
581        tuple_seq_as_map_impl_intern!($tyorig<(K, V) $(, $typaram: $bound)* >, BTreeMap<K, V>);
582        #[cfg(feature = "std")]
583        tuple_seq_as_map_impl_intern!($tyorig<(K, V) $(, $typaram: $bound)* >, HashMap<K, V>);
584    }
585}
586foreach_seq!(tuple_seq_as_map_impl, (K, V));
587tuple_seq_as_map_impl!(Option<(K, V)>);
588
589macro_rules! tuple_seq_as_map_arr {
590    ($tyorig:ty, $ty:ident <K, V>) => {
591        #[allow(clippy::implicit_hasher)]
592        impl<K, KAs, V, VAs, const N: usize> SerializeAs<$tyorig> for $ty<KAs, VAs>
593        where
594            KAs: SerializeAs<K>,
595            VAs: SerializeAs<V>,
596        {
597            fn serialize_as<S>(source: &$tyorig, serializer: S) -> Result<S::Ok, S::Error>
598            where
599                S: Serializer,
600            {
601                serializer.collect_map(source.iter().map(|(k, v)| {
602                    (
603                        SerializeAsWrap::<K, KAs>::new(k),
604                        SerializeAsWrap::<V, VAs>::new(v),
605                    )
606                }))
607            }
608        }
609    };
610}
611tuple_seq_as_map_arr!([(K, V); N], Map<K, V>);
612#[cfg(feature = "alloc")]
613tuple_seq_as_map_arr!([(K, V); N], BTreeMap<K, V>);
614#[cfg(feature = "std")]
615tuple_seq_as_map_arr!([(K, V); N], HashMap<K, V>);
616
617// endregion
618///////////////////////////////////////////////////////////////////////////////
619// region: Conversion types which cause different serialization behavior
620
621impl<T> SerializeAs<T> for Same
622where
623    T: Serialize + ?Sized,
624{
625    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
626    where
627        S: Serializer,
628    {
629        source.serialize(serializer)
630    }
631}
632
633impl<T> SerializeAs<T> for DisplayFromStr
634where
635    T: Display,
636{
637    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
638    where
639        S: Serializer,
640    {
641        serializer.collect_str(source)
642    }
643}
644
645impl<T, H, F> SerializeAs<T> for IfIsHumanReadable<H, F>
646where
647    T: ?Sized,
648    H: SerializeAs<T>,
649    F: SerializeAs<T>,
650{
651    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
652    where
653        S: Serializer,
654    {
655        if serializer.is_human_readable() {
656            H::serialize_as(source, serializer)
657        } else {
658            F::serialize_as(source, serializer)
659        }
660    }
661}
662
663impl<T> SerializeAs<Option<T>> for NoneAsEmptyString
664where
665    T: Display,
666{
667    fn serialize_as<S>(source: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
668    where
669        S: Serializer,
670    {
671        if let Some(value) = source {
672            serializer.collect_str(value)
673        } else {
674            serializer.serialize_str("")
675        }
676    }
677}
678
679macro_rules! none_as_zero_serialize {
680    ($($nonzero:ident => $primitive:ident),* $(,)?) => {
681        $(
682            impl SerializeAs<Option<core::num::$nonzero>> for NoneAsZero {
683                fn serialize_as<S>(
684                    source: &Option<core::num::$nonzero>,
685                    serializer: S,
686                ) -> Result<S::Ok, S::Error>
687                where
688                    S: Serializer,
689                {
690                    let value: $primitive = source.map_or(0, core::num::$nonzero::get);
691                    value.serialize(serializer)
692                }
693            }
694        )*
695    };
696}
697
698none_as_zero_serialize! {
699    NonZeroU8    => u8,
700    NonZeroU16   => u16,
701    NonZeroU32   => u32,
702    NonZeroU64   => u64,
703    NonZeroU128  => u128,
704    NonZeroUsize => usize,
705    NonZeroI8    => i8,
706    NonZeroI16   => i16,
707    NonZeroI32   => i32,
708    NonZeroI64   => i64,
709    NonZeroI128  => i128,
710    NonZeroIsize => isize,
711}
712
713#[cfg(feature = "alloc")]
714impl<T, TAs> SerializeAs<T> for DefaultOnError<TAs>
715where
716    TAs: SerializeAs<T>,
717{
718    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
719    where
720        S: Serializer,
721    {
722        TAs::serialize_as(source, serializer)
723    }
724}
725
726#[cfg(feature = "alloc")]
727impl SerializeAs<Vec<u8>> for BytesOrString {
728    fn serialize_as<S>(source: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
729    where
730        S: Serializer,
731    {
732        source.serialize(serializer)
733    }
734}
735
736impl<SEPARATOR, I, T> SerializeAs<I> for StringWithSeparator<SEPARATOR, T>
737where
738    SEPARATOR: formats::Separator,
739    for<'x> &'x I: IntoIterator<Item = &'x T>,
740    T: Display,
741    // This set of bounds is enough to make the function compile but has inference issues
742    // making it unusable at the moment.
743    // https://github.com/rust-lang/rust/issues/89196#issuecomment-932024770
744    // for<'x> &'x I: IntoIterator,
745    // for<'x> <&'x I as IntoIterator>::Item: Display,
746{
747    fn serialize_as<S>(source: &I, serializer: S) -> Result<S::Ok, S::Error>
748    where
749        S: Serializer,
750    {
751        pub(crate) struct DisplayWithSeparator<'a, I, SEPARATOR>(&'a I, PhantomData<SEPARATOR>);
752
753        impl<'a, I, SEPARATOR> DisplayWithSeparator<'a, I, SEPARATOR> {
754            pub(crate) fn new(iter: &'a I) -> Self {
755                Self(iter, PhantomData)
756            }
757        }
758
759        impl<'a, I, SEPARATOR> Display for DisplayWithSeparator<'a, I, SEPARATOR>
760        where
761            SEPARATOR: formats::Separator,
762            &'a I: IntoIterator,
763            <&'a I as IntoIterator>::Item: Display,
764        {
765            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
766                let mut iter = self.0.into_iter();
767
768                if let Some(first) = iter.next() {
769                    first.fmt(f)?;
770                }
771                for elem in iter {
772                    f.write_str(SEPARATOR::separator())?;
773                    elem.fmt(f)?;
774                }
775
776                Ok(())
777            }
778        }
779
780        serializer.collect_str(&DisplayWithSeparator::<I, SEPARATOR>::new(source))
781    }
782}
783
784macro_rules! use_signed_duration {
785    (
786        $main_trait:ident $internal_trait:ident =>
787        {
788            $ty:ty =>
789            $({
790                $format:ty, $strictness:ty =>
791                $($tbound:ident: $bound:ident $(,)?)*
792            })*
793        }
794    ) => {
795        $(
796            impl<$($tbound,)*> SerializeAs<$ty> for $main_trait<$format, $strictness>
797            where
798                $($tbound: $bound,)*
799            {
800                fn serialize_as<S>(source: &$ty, serializer: S) -> Result<S::Ok, S::Error>
801                where
802                    S: Serializer,
803                {
804                    $internal_trait::<$format, $strictness>::serialize_as(
805                        &DurationSigned::from(source),
806                        serializer,
807                    )
808                }
809            }
810        )*
811    };
812    (
813        $( $main_trait:ident $internal_trait:ident, )+ => $rest:tt
814    ) => {
815        $( use_signed_duration!($main_trait $internal_trait => $rest); )+
816    };
817}
818
819use_signed_duration!(
820    DurationSeconds DurationSeconds,
821    DurationMilliSeconds DurationMilliSeconds,
822    DurationMicroSeconds DurationMicroSeconds,
823    DurationNanoSeconds DurationNanoSeconds,
824    => {
825        Duration =>
826        {u64, STRICTNESS => STRICTNESS: Strictness}
827        {f64, STRICTNESS => STRICTNESS: Strictness}
828    }
829);
830#[cfg(feature = "alloc")]
831use_signed_duration!(
832    DurationSeconds DurationSeconds,
833    DurationMilliSeconds DurationMilliSeconds,
834    DurationMicroSeconds DurationMicroSeconds,
835    DurationNanoSeconds DurationNanoSeconds,
836    => {
837        Duration =>
838        {String, STRICTNESS => STRICTNESS: Strictness}
839    }
840);
841use_signed_duration!(
842    DurationSecondsWithFrac DurationSecondsWithFrac,
843    DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac,
844    DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac,
845    DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac,
846    => {
847        Duration =>
848        {f64, STRICTNESS => STRICTNESS: Strictness}
849    }
850);
851#[cfg(feature = "alloc")]
852use_signed_duration!(
853    DurationSecondsWithFrac DurationSecondsWithFrac,
854    DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac,
855    DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac,
856    DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac,
857    => {
858        Duration =>
859        {String, STRICTNESS => STRICTNESS: Strictness}
860    }
861);
862
863#[cfg(feature = "std")]
864use_signed_duration!(
865    TimestampSeconds DurationSeconds,
866    TimestampMilliSeconds DurationMilliSeconds,
867    TimestampMicroSeconds DurationMicroSeconds,
868    TimestampNanoSeconds DurationNanoSeconds,
869    => {
870        SystemTime =>
871        {i64, STRICTNESS => STRICTNESS: Strictness}
872        {f64, STRICTNESS => STRICTNESS: Strictness}
873        {String, STRICTNESS => STRICTNESS: Strictness}
874    }
875);
876#[cfg(feature = "std")]
877use_signed_duration!(
878    TimestampSecondsWithFrac DurationSecondsWithFrac,
879    TimestampMilliSecondsWithFrac DurationMilliSecondsWithFrac,
880    TimestampMicroSecondsWithFrac DurationMicroSecondsWithFrac,
881    TimestampNanoSecondsWithFrac DurationNanoSecondsWithFrac,
882    => {
883        SystemTime =>
884        {f64, STRICTNESS => STRICTNESS: Strictness}
885        {String, STRICTNESS => STRICTNESS: Strictness}
886    }
887);
888
889impl<T, U> SerializeAs<T> for DefaultOnNull<U>
890where
891    U: SerializeAs<T>,
892{
893    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
894    where
895        S: Serializer,
896    {
897        serializer.serialize_some(&SerializeAsWrap::<T, U>::new(source))
898    }
899}
900
901impl SerializeAs<&[u8]> for Bytes {
902    fn serialize_as<S>(bytes: &&[u8], serializer: S) -> Result<S::Ok, S::Error>
903    where
904        S: Serializer,
905    {
906        serializer.serialize_bytes(bytes)
907    }
908}
909
910#[cfg(feature = "alloc")]
911impl SerializeAs<Vec<u8>> for Bytes {
912    fn serialize_as<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
913    where
914        S: Serializer,
915    {
916        serializer.serialize_bytes(bytes)
917    }
918}
919
920#[cfg(feature = "alloc")]
921impl SerializeAs<Box<[u8]>> for Bytes {
922    fn serialize_as<S>(bytes: &Box<[u8]>, serializer: S) -> Result<S::Ok, S::Error>
923    where
924        S: Serializer,
925    {
926        serializer.serialize_bytes(bytes)
927    }
928}
929
930#[cfg(feature = "alloc")]
931impl<'a> SerializeAs<Cow<'a, [u8]>> for Bytes {
932    fn serialize_as<S>(bytes: &Cow<'a, [u8]>, serializer: S) -> Result<S::Ok, S::Error>
933    where
934        S: Serializer,
935    {
936        serializer.serialize_bytes(bytes)
937    }
938}
939
940impl<const N: usize> SerializeAs<[u8; N]> for Bytes {
941    fn serialize_as<S>(bytes: &[u8; N], serializer: S) -> Result<S::Ok, S::Error>
942    where
943        S: Serializer,
944    {
945        serializer.serialize_bytes(bytes)
946    }
947}
948
949impl<const N: usize> SerializeAs<&[u8; N]> for Bytes {
950    fn serialize_as<S>(bytes: &&[u8; N], serializer: S) -> Result<S::Ok, S::Error>
951    where
952        S: Serializer,
953    {
954        serializer.serialize_bytes(*bytes)
955    }
956}
957
958#[cfg(feature = "alloc")]
959impl<const N: usize> SerializeAs<Box<[u8; N]>> for Bytes {
960    fn serialize_as<S>(bytes: &Box<[u8; N]>, serializer: S) -> Result<S::Ok, S::Error>
961    where
962        S: Serializer,
963    {
964        serializer.serialize_bytes(&**bytes)
965    }
966}
967
968#[cfg(feature = "alloc")]
969impl<'a, const N: usize> SerializeAs<Cow<'a, [u8; N]>> for Bytes {
970    fn serialize_as<S>(bytes: &Cow<'a, [u8; N]>, serializer: S) -> Result<S::Ok, S::Error>
971    where
972        S: Serializer,
973    {
974        serializer.serialize_bytes(bytes.as_ref())
975    }
976}
977
978#[cfg(feature = "alloc")]
979macro_rules! one_or_many_impl {
980    ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident )* >) => {
981        impl<T, U $(, $typaram)*> SerializeAs<$ty<T $(, $typaram)*>> for OneOrMany<U, formats::PreferOne>
982        where
983            U: SerializeAs<T>,
984            $(T: ?Sized + $tbound1 $(+ $tbound2)*,)*
985            $($typaram: ?Sized + $bound,)*
986        {
987            fn serialize_as<S>(source: &$ty<T $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
988            where
989                S: Serializer,
990            {
991                match source.len() {
992                    1 => SerializeAsWrap::<T, U>::new(source.iter().next().expect("Cannot be empty"))
993                        .serialize(serializer),
994                    _ => serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::<T, U>::new(item))),
995                }
996            }
997        }
998
999        impl<T, U $(, $typaram)*> SerializeAs<$ty<T $(, $typaram)*>> for OneOrMany<U, formats::PreferMany>
1000        where
1001            U: SerializeAs<T>,
1002            $(T: ?Sized + $tbound1 $(+ $tbound2)*,)*
1003            $($typaram: ?Sized + $bound,)*
1004        {
1005            fn serialize_as<S>(source: &$ty<T $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
1006            where
1007                S: Serializer,
1008            {
1009                serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::<T, U>::new(item)))
1010            }
1011        }
1012    }
1013}
1014#[cfg(feature = "alloc")]
1015foreach_seq!(one_or_many_impl);
1016
1017#[cfg(all(feature = "alloc", feature = "smallvec_1"))]
1018impl<T, TAs, A> SerializeAs<SmallVec<A>> for OneOrMany<TAs, formats::PreferOne>
1019where
1020    A: smallvec_1::Array<Item = T>,
1021    TAs: SerializeAs<T>,
1022{
1023    fn serialize_as<S>(source: &SmallVec<A>, serializer: S) -> Result<S::Ok, S::Error>
1024    where
1025        S: Serializer,
1026    {
1027        match source.len() {
1028            1 => SerializeAsWrap::<T, TAs>::new(source.iter().next().expect("Cannot be empty"))
1029                .serialize(serializer),
1030            _ => SerializeAsWrap::<&[T], &[TAs]>::new(&source.as_slice()).serialize(serializer),
1031        }
1032    }
1033}
1034
1035#[cfg(all(feature = "alloc", feature = "smallvec_1"))]
1036impl<T, TAs, A> SerializeAs<SmallVec<A>> for OneOrMany<TAs, formats::PreferMany>
1037where
1038    A: smallvec_1::Array<Item = T>,
1039    TAs: SerializeAs<T>,
1040{
1041    fn serialize_as<S>(source: &SmallVec<A>, serializer: S) -> Result<S::Ok, S::Error>
1042    where
1043        S: Serializer,
1044    {
1045        SerializeAsWrap::<&[T], &[TAs]>::new(&source.as_slice()).serialize(serializer)
1046    }
1047}
1048
1049#[cfg(feature = "alloc")]
1050impl<T, TAs1> SerializeAs<T> for PickFirst<(TAs1,)>
1051where
1052    TAs1: SerializeAs<T>,
1053{
1054    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1055    where
1056        S: Serializer,
1057    {
1058        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1059    }
1060}
1061
1062#[cfg(feature = "alloc")]
1063impl<T, TAs1, TAs2> SerializeAs<T> for PickFirst<(TAs1, TAs2)>
1064where
1065    TAs1: SerializeAs<T>,
1066{
1067    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1068    where
1069        S: Serializer,
1070    {
1071        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1072    }
1073}
1074
1075#[cfg(feature = "alloc")]
1076impl<T, TAs1, TAs2, TAs3> SerializeAs<T> for PickFirst<(TAs1, TAs2, TAs3)>
1077where
1078    TAs1: SerializeAs<T>,
1079{
1080    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1081    where
1082        S: Serializer,
1083    {
1084        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1085    }
1086}
1087
1088#[cfg(feature = "alloc")]
1089impl<T, TAs1, TAs2, TAs3, TAs4> SerializeAs<T> for PickFirst<(TAs1, TAs2, TAs3, TAs4)>
1090where
1091    TAs1: SerializeAs<T>,
1092{
1093    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1094    where
1095        S: Serializer,
1096    {
1097        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1098    }
1099}
1100
1101impl<T, U> SerializeAs<T> for FromInto<U>
1102where
1103    T: Into<U> + Clone,
1104    U: Serialize,
1105{
1106    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1107    where
1108        S: Serializer,
1109    {
1110        source.clone().into().serialize(serializer)
1111    }
1112}
1113
1114impl<T, U> SerializeAs<T> for TryFromInto<U>
1115where
1116    T: TryInto<U> + Clone,
1117    <T as TryInto<U>>::Error: Display,
1118    U: Serialize,
1119{
1120    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1121    where
1122        S: Serializer,
1123    {
1124        source
1125            .clone()
1126            .try_into()
1127            .map_err(S::Error::custom)?
1128            .serialize(serializer)
1129    }
1130}
1131
1132impl<T, U> SerializeAs<T> for FromIntoRef<U>
1133where
1134    for<'a> &'a T: Into<U>,
1135    U: Serialize,
1136{
1137    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1138    where
1139        S: Serializer,
1140    {
1141        source.into().serialize(serializer)
1142    }
1143}
1144
1145impl<T, U> SerializeAs<T> for TryFromIntoRef<U>
1146where
1147    for<'a> &'a T: TryInto<U>,
1148    for<'a> <&'a T as TryInto<U>>::Error: Display,
1149    U: Serialize,
1150{
1151    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1152    where
1153        S: Serializer,
1154    {
1155        source
1156            .try_into()
1157            .map_err(S::Error::custom)?
1158            .serialize(serializer)
1159    }
1160}
1161
1162#[cfg(feature = "alloc")]
1163impl<'a> SerializeAs<Cow<'a, str>> for BorrowCow {
1164    fn serialize_as<S>(source: &Cow<'a, str>, serializer: S) -> Result<S::Ok, S::Error>
1165    where
1166        S: Serializer,
1167    {
1168        serializer.serialize_str(source)
1169    }
1170}
1171
1172#[cfg(feature = "alloc")]
1173impl<'a> SerializeAs<Cow<'a, [u8]>> for BorrowCow {
1174    fn serialize_as<S>(value: &Cow<'a, [u8]>, serializer: S) -> Result<S::Ok, S::Error>
1175    where
1176        S: Serializer,
1177    {
1178        serializer.collect_seq(value.iter())
1179    }
1180}
1181
1182#[cfg(feature = "alloc")]
1183impl<'a, const N: usize> SerializeAs<Cow<'a, [u8; N]>> for BorrowCow {
1184    fn serialize_as<S>(value: &Cow<'a, [u8; N]>, serializer: S) -> Result<S::Ok, S::Error>
1185    where
1186        S: Serializer,
1187    {
1188        serializer.collect_seq(value.iter())
1189    }
1190}
1191
1192impl<STRICTNESS: Strictness> SerializeAs<bool> for BoolFromInt<STRICTNESS> {
1193    fn serialize_as<S>(source: &bool, serializer: S) -> Result<S::Ok, S::Error>
1194    where
1195        S: Serializer,
1196    {
1197        serializer.serialize_u8(u8::from(*source))
1198    }
1199}
1200
1201// endregion