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
679#[cfg(feature = "alloc")]
680impl<T, TAs> SerializeAs<T> for DefaultOnError<TAs>
681where
682    TAs: SerializeAs<T>,
683{
684    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
685    where
686        S: Serializer,
687    {
688        TAs::serialize_as(source, serializer)
689    }
690}
691
692#[cfg(feature = "alloc")]
693impl SerializeAs<Vec<u8>> for BytesOrString {
694    fn serialize_as<S>(source: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
695    where
696        S: Serializer,
697    {
698        source.serialize(serializer)
699    }
700}
701
702impl<SEPARATOR, I, T> SerializeAs<I> for StringWithSeparator<SEPARATOR, T>
703where
704    SEPARATOR: formats::Separator,
705    for<'x> &'x I: IntoIterator<Item = &'x T>,
706    T: Display,
707    // This set of bounds is enough to make the function compile but has inference issues
708    // making it unusable at the moment.
709    // https://github.com/rust-lang/rust/issues/89196#issuecomment-932024770
710    // for<'x> &'x I: IntoIterator,
711    // for<'x> <&'x I as IntoIterator>::Item: Display,
712{
713    fn serialize_as<S>(source: &I, serializer: S) -> Result<S::Ok, S::Error>
714    where
715        S: Serializer,
716    {
717        pub(crate) struct DisplayWithSeparator<'a, I, SEPARATOR>(&'a I, PhantomData<SEPARATOR>);
718
719        impl<'a, I, SEPARATOR> DisplayWithSeparator<'a, I, SEPARATOR> {
720            pub(crate) fn new(iter: &'a I) -> Self {
721                Self(iter, PhantomData)
722            }
723        }
724
725        impl<'a, I, SEPARATOR> Display for DisplayWithSeparator<'a, I, SEPARATOR>
726        where
727            SEPARATOR: formats::Separator,
728            &'a I: IntoIterator,
729            <&'a I as IntoIterator>::Item: Display,
730        {
731            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
732                let mut iter = self.0.into_iter();
733
734                if let Some(first) = iter.next() {
735                    first.fmt(f)?;
736                }
737                for elem in iter {
738                    f.write_str(SEPARATOR::separator())?;
739                    elem.fmt(f)?;
740                }
741
742                Ok(())
743            }
744        }
745
746        serializer.collect_str(&DisplayWithSeparator::<I, SEPARATOR>::new(source))
747    }
748}
749
750macro_rules! use_signed_duration {
751    (
752        $main_trait:ident $internal_trait:ident =>
753        {
754            $ty:ty =>
755            $({
756                $format:ty, $strictness:ty =>
757                $($tbound:ident: $bound:ident $(,)?)*
758            })*
759        }
760    ) => {
761        $(
762            impl<$($tbound,)*> SerializeAs<$ty> for $main_trait<$format, $strictness>
763            where
764                $($tbound: $bound,)*
765            {
766                fn serialize_as<S>(source: &$ty, serializer: S) -> Result<S::Ok, S::Error>
767                where
768                    S: Serializer,
769                {
770                    $internal_trait::<$format, $strictness>::serialize_as(
771                        &DurationSigned::from(source),
772                        serializer,
773                    )
774                }
775            }
776        )*
777    };
778    (
779        $( $main_trait:ident $internal_trait:ident, )+ => $rest:tt
780    ) => {
781        $( use_signed_duration!($main_trait $internal_trait => $rest); )+
782    };
783}
784
785use_signed_duration!(
786    DurationSeconds DurationSeconds,
787    DurationMilliSeconds DurationMilliSeconds,
788    DurationMicroSeconds DurationMicroSeconds,
789    DurationNanoSeconds DurationNanoSeconds,
790    => {
791        Duration =>
792        {u64, STRICTNESS => STRICTNESS: Strictness}
793        {f64, STRICTNESS => STRICTNESS: Strictness}
794    }
795);
796#[cfg(feature = "alloc")]
797use_signed_duration!(
798    DurationSeconds DurationSeconds,
799    DurationMilliSeconds DurationMilliSeconds,
800    DurationMicroSeconds DurationMicroSeconds,
801    DurationNanoSeconds DurationNanoSeconds,
802    => {
803        Duration =>
804        {String, STRICTNESS => STRICTNESS: Strictness}
805    }
806);
807use_signed_duration!(
808    DurationSecondsWithFrac DurationSecondsWithFrac,
809    DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac,
810    DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac,
811    DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac,
812    => {
813        Duration =>
814        {f64, STRICTNESS => STRICTNESS: Strictness}
815    }
816);
817#[cfg(feature = "alloc")]
818use_signed_duration!(
819    DurationSecondsWithFrac DurationSecondsWithFrac,
820    DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac,
821    DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac,
822    DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac,
823    => {
824        Duration =>
825        {String, STRICTNESS => STRICTNESS: Strictness}
826    }
827);
828
829#[cfg(feature = "std")]
830use_signed_duration!(
831    TimestampSeconds DurationSeconds,
832    TimestampMilliSeconds DurationMilliSeconds,
833    TimestampMicroSeconds DurationMicroSeconds,
834    TimestampNanoSeconds DurationNanoSeconds,
835    => {
836        SystemTime =>
837        {i64, STRICTNESS => STRICTNESS: Strictness}
838        {f64, STRICTNESS => STRICTNESS: Strictness}
839        {String, STRICTNESS => STRICTNESS: Strictness}
840    }
841);
842#[cfg(feature = "std")]
843use_signed_duration!(
844    TimestampSecondsWithFrac DurationSecondsWithFrac,
845    TimestampMilliSecondsWithFrac DurationMilliSecondsWithFrac,
846    TimestampMicroSecondsWithFrac DurationMicroSecondsWithFrac,
847    TimestampNanoSecondsWithFrac DurationNanoSecondsWithFrac,
848    => {
849        SystemTime =>
850        {f64, STRICTNESS => STRICTNESS: Strictness}
851        {String, STRICTNESS => STRICTNESS: Strictness}
852    }
853);
854
855impl<T, U> SerializeAs<T> for DefaultOnNull<U>
856where
857    U: SerializeAs<T>,
858{
859    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
860    where
861        S: Serializer,
862    {
863        serializer.serialize_some(&SerializeAsWrap::<T, U>::new(source))
864    }
865}
866
867impl SerializeAs<&[u8]> for Bytes {
868    fn serialize_as<S>(bytes: &&[u8], serializer: S) -> Result<S::Ok, S::Error>
869    where
870        S: Serializer,
871    {
872        serializer.serialize_bytes(bytes)
873    }
874}
875
876#[cfg(feature = "alloc")]
877impl SerializeAs<Vec<u8>> for Bytes {
878    fn serialize_as<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
879    where
880        S: Serializer,
881    {
882        serializer.serialize_bytes(bytes)
883    }
884}
885
886#[cfg(feature = "alloc")]
887impl SerializeAs<Box<[u8]>> for Bytes {
888    fn serialize_as<S>(bytes: &Box<[u8]>, serializer: S) -> Result<S::Ok, S::Error>
889    where
890        S: Serializer,
891    {
892        serializer.serialize_bytes(bytes)
893    }
894}
895
896#[cfg(feature = "alloc")]
897impl<'a> SerializeAs<Cow<'a, [u8]>> for Bytes {
898    fn serialize_as<S>(bytes: &Cow<'a, [u8]>, serializer: S) -> Result<S::Ok, S::Error>
899    where
900        S: Serializer,
901    {
902        serializer.serialize_bytes(bytes)
903    }
904}
905
906impl<const N: usize> SerializeAs<[u8; N]> for Bytes {
907    fn serialize_as<S>(bytes: &[u8; N], serializer: S) -> Result<S::Ok, S::Error>
908    where
909        S: Serializer,
910    {
911        serializer.serialize_bytes(bytes)
912    }
913}
914
915impl<const N: usize> SerializeAs<&[u8; N]> for Bytes {
916    fn serialize_as<S>(bytes: &&[u8; N], serializer: S) -> Result<S::Ok, S::Error>
917    where
918        S: Serializer,
919    {
920        serializer.serialize_bytes(*bytes)
921    }
922}
923
924#[cfg(feature = "alloc")]
925impl<const N: usize> SerializeAs<Box<[u8; N]>> for Bytes {
926    fn serialize_as<S>(bytes: &Box<[u8; N]>, serializer: S) -> Result<S::Ok, S::Error>
927    where
928        S: Serializer,
929    {
930        serializer.serialize_bytes(&**bytes)
931    }
932}
933
934#[cfg(feature = "alloc")]
935impl<'a, const N: usize> SerializeAs<Cow<'a, [u8; N]>> for Bytes {
936    fn serialize_as<S>(bytes: &Cow<'a, [u8; N]>, serializer: S) -> Result<S::Ok, S::Error>
937    where
938        S: Serializer,
939    {
940        serializer.serialize_bytes(bytes.as_ref())
941    }
942}
943
944#[cfg(feature = "alloc")]
945macro_rules! one_or_many_impl {
946    ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident )* >) => {
947        impl<T, U $(, $typaram)*> SerializeAs<$ty<T $(, $typaram)*>> for OneOrMany<U, formats::PreferOne>
948        where
949            U: SerializeAs<T>,
950            $(T: ?Sized + $tbound1 $(+ $tbound2)*,)*
951            $($typaram: ?Sized + $bound,)*
952        {
953            fn serialize_as<S>(source: &$ty<T $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
954            where
955                S: Serializer,
956            {
957                match source.len() {
958                    1 => SerializeAsWrap::<T, U>::new(source.iter().next().expect("Cannot be empty"))
959                        .serialize(serializer),
960                    _ => serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::<T, U>::new(item))),
961                }
962            }
963        }
964
965        impl<T, U $(, $typaram)*> SerializeAs<$ty<T $(, $typaram)*>> for OneOrMany<U, formats::PreferMany>
966        where
967            U: SerializeAs<T>,
968            $(T: ?Sized + $tbound1 $(+ $tbound2)*,)*
969            $($typaram: ?Sized + $bound,)*
970        {
971            fn serialize_as<S>(source: &$ty<T $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
972            where
973                S: Serializer,
974            {
975                serializer.collect_seq(source.iter().map(|item| SerializeAsWrap::<T, U>::new(item)))
976            }
977        }
978    }
979}
980#[cfg(feature = "alloc")]
981foreach_seq!(one_or_many_impl);
982
983#[cfg(all(feature = "alloc", feature = "smallvec_1"))]
984impl<T, TAs, A> SerializeAs<smallvec_1::SmallVec<A>> for OneOrMany<TAs, formats::PreferOne>
985where
986    A: smallvec_1::Array<Item = T>,
987    TAs: SerializeAs<T>,
988{
989    fn serialize_as<S>(source: &smallvec_1::SmallVec<A>, serializer: S) -> Result<S::Ok, S::Error>
990    where
991        S: Serializer,
992    {
993        match source.len() {
994            1 => SerializeAsWrap::<T, TAs>::new(source.iter().next().expect("Cannot be empty"))
995                .serialize(serializer),
996            _ => SerializeAsWrap::<&[T], &[TAs]>::new(&source.as_slice()).serialize(serializer),
997        }
998    }
999}
1000
1001#[cfg(all(feature = "alloc", feature = "smallvec_1"))]
1002impl<T, TAs, A> SerializeAs<smallvec_1::SmallVec<A>> for OneOrMany<TAs, formats::PreferMany>
1003where
1004    A: smallvec_1::Array<Item = T>,
1005    TAs: SerializeAs<T>,
1006{
1007    fn serialize_as<S>(source: &smallvec_1::SmallVec<A>, serializer: S) -> Result<S::Ok, S::Error>
1008    where
1009        S: Serializer,
1010    {
1011        SerializeAsWrap::<&[T], &[TAs]>::new(&source.as_slice()).serialize(serializer)
1012    }
1013}
1014
1015#[cfg(feature = "alloc")]
1016impl<T, TAs1> SerializeAs<T> for PickFirst<(TAs1,)>
1017where
1018    TAs1: SerializeAs<T>,
1019{
1020    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1021    where
1022        S: Serializer,
1023    {
1024        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1025    }
1026}
1027
1028#[cfg(feature = "alloc")]
1029impl<T, TAs1, TAs2> SerializeAs<T> for PickFirst<(TAs1, TAs2)>
1030where
1031    TAs1: SerializeAs<T>,
1032{
1033    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1034    where
1035        S: Serializer,
1036    {
1037        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1038    }
1039}
1040
1041#[cfg(feature = "alloc")]
1042impl<T, TAs1, TAs2, TAs3> SerializeAs<T> for PickFirst<(TAs1, TAs2, TAs3)>
1043where
1044    TAs1: SerializeAs<T>,
1045{
1046    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1047    where
1048        S: Serializer,
1049    {
1050        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1051    }
1052}
1053
1054#[cfg(feature = "alloc")]
1055impl<T, TAs1, TAs2, TAs3, TAs4> SerializeAs<T> for PickFirst<(TAs1, TAs2, TAs3, TAs4)>
1056where
1057    TAs1: SerializeAs<T>,
1058{
1059    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1060    where
1061        S: Serializer,
1062    {
1063        SerializeAsWrap::<T, TAs1>::new(source).serialize(serializer)
1064    }
1065}
1066
1067impl<T, U> SerializeAs<T> for FromInto<U>
1068where
1069    T: Into<U> + Clone,
1070    U: Serialize,
1071{
1072    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1073    where
1074        S: Serializer,
1075    {
1076        source.clone().into().serialize(serializer)
1077    }
1078}
1079
1080impl<T, U> SerializeAs<T> for TryFromInto<U>
1081where
1082    T: TryInto<U> + Clone,
1083    <T as TryInto<U>>::Error: Display,
1084    U: Serialize,
1085{
1086    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1087    where
1088        S: Serializer,
1089    {
1090        source
1091            .clone()
1092            .try_into()
1093            .map_err(S::Error::custom)?
1094            .serialize(serializer)
1095    }
1096}
1097
1098impl<T, U> SerializeAs<T> for FromIntoRef<U>
1099where
1100    for<'a> &'a T: Into<U>,
1101    U: Serialize,
1102{
1103    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1104    where
1105        S: Serializer,
1106    {
1107        source.into().serialize(serializer)
1108    }
1109}
1110
1111impl<T, U> SerializeAs<T> for TryFromIntoRef<U>
1112where
1113    for<'a> &'a T: TryInto<U>,
1114    for<'a> <&'a T as TryInto<U>>::Error: Display,
1115    U: Serialize,
1116{
1117    fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
1118    where
1119        S: Serializer,
1120    {
1121        source
1122            .try_into()
1123            .map_err(S::Error::custom)?
1124            .serialize(serializer)
1125    }
1126}
1127
1128#[cfg(feature = "alloc")]
1129impl<'a> SerializeAs<Cow<'a, str>> for BorrowCow {
1130    fn serialize_as<S>(source: &Cow<'a, str>, serializer: S) -> Result<S::Ok, S::Error>
1131    where
1132        S: Serializer,
1133    {
1134        serializer.serialize_str(source)
1135    }
1136}
1137
1138#[cfg(feature = "alloc")]
1139impl<'a> SerializeAs<Cow<'a, [u8]>> for BorrowCow {
1140    fn serialize_as<S>(value: &Cow<'a, [u8]>, serializer: S) -> Result<S::Ok, S::Error>
1141    where
1142        S: Serializer,
1143    {
1144        serializer.collect_seq(value.iter())
1145    }
1146}
1147
1148#[cfg(feature = "alloc")]
1149impl<'a, const N: usize> SerializeAs<Cow<'a, [u8; N]>> for BorrowCow {
1150    fn serialize_as<S>(value: &Cow<'a, [u8; N]>, serializer: S) -> Result<S::Ok, S::Error>
1151    where
1152        S: Serializer,
1153    {
1154        serializer.collect_seq(value.iter())
1155    }
1156}
1157
1158impl<STRICTNESS: Strictness> SerializeAs<bool> for BoolFromInt<STRICTNESS> {
1159    fn serialize_as<S>(source: &bool, serializer: S) -> Result<S::Ok, S::Error>
1160    where
1161        S: Serializer,
1162    {
1163        serializer.serialize_u8(u8::from(*source))
1164    }
1165}
1166
1167// endregion