musli_core/impls/
alloc.rs

1use core::ffi::CStr;
2use core::fmt;
3#[cfg(feature = "std")]
4use core::hash::{BuildHasher, Hash};
5
6use rust_alloc::borrow::{Cow, ToOwned};
7use rust_alloc::boxed::Box;
8use rust_alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, VecDeque};
9use rust_alloc::ffi::CString;
10use rust_alloc::rc::Rc;
11use rust_alloc::string::String;
12use rust_alloc::sync::Arc;
13use rust_alloc::vec::Vec;
14
15#[cfg(feature = "std")]
16use std::collections::{HashMap, HashSet};
17#[cfg(all(feature = "std", any(unix, windows)))]
18use std::ffi::{OsStr, OsString};
19#[cfg(all(feature = "std", any(unix, windows)))]
20use std::path::{Path, PathBuf};
21
22use crate::de::{
23    Decode, DecodeBytes, DecodeTrace, Decoder, EntryDecoder, MapDecoder, SequenceDecoder,
24    UnsizedVisitor,
25};
26use crate::en::{
27    Encode, EncodeBytes, EncodePacked, EncodeTrace, Encoder, EntryEncoder, MapEncoder,
28    SequenceEncoder,
29};
30use crate::hint::{MapHint, SequenceHint};
31use crate::internal::size_hint;
32use crate::Context;
33
34#[cfg(all(feature = "std", any(unix, windows)))]
35use super::PlatformTag;
36
37impl<M> Encode<M> for String {
38    #[inline]
39    fn encode<E>(&self, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
40    where
41        E: Encoder<Mode = M>,
42    {
43        self.as_str().encode(cx, encoder)
44    }
45}
46
47impl<'de, M> Decode<'de, M> for String {
48    #[inline]
49    fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
50    where
51        D: Decoder<'de, Mode = M>,
52    {
53        struct Visitor;
54
55        impl<'de, C> UnsizedVisitor<'de, C, str> for Visitor
56        where
57            C: ?Sized + Context,
58        {
59            type Ok = String;
60
61            #[inline]
62            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63                write!(f, "string")
64            }
65
66            #[inline]
67            fn visit_owned(self, _: &C, value: String) -> Result<Self::Ok, C::Error> {
68                Ok(value)
69            }
70
71            #[inline]
72            fn visit_borrowed(self, cx: &C, string: &'de str) -> Result<Self::Ok, C::Error> {
73                self.visit_ref(cx, string)
74            }
75
76            #[inline]
77            fn visit_ref(self, _: &C, string: &str) -> Result<Self::Ok, C::Error> {
78                Ok(string.to_owned())
79            }
80        }
81
82        decoder.decode_string(Visitor)
83    }
84}
85
86impl<'de, M> Decode<'de, M> for Box<str> {
87    #[inline]
88    fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
89    where
90        D: Decoder<'de, Mode = M>,
91    {
92        Ok(decoder.decode::<String>()?.into())
93    }
94}
95
96impl<'de, M, T> Decode<'de, M> for Box<[T]>
97where
98    T: Decode<'de, M>,
99{
100    #[inline]
101    fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
102    where
103        D: Decoder<'de, Mode = M>,
104    {
105        Ok(decoder.decode::<Vec<T>>()?.into())
106    }
107}
108
109macro_rules! cow {
110    (
111        $encode:ident :: $encode_fn:ident,
112        $decode:ident :: $decode_fn:ident,
113        $ty:ty, $source:ty,
114        $decode_method:ident, $cx:pat,
115        |$owned:ident| $owned_expr:expr,
116        |$borrowed:ident| $borrowed_expr:expr,
117        |$reference:ident| $reference_expr:expr $(,)?
118    ) => {
119        impl<M> $encode<M> for Cow<'_, $ty> {
120            #[inline]
121            fn $encode_fn<E>(&self, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
122            where
123                E: Encoder<Mode = M>,
124            {
125                self.as_ref().$encode_fn(cx, encoder)
126            }
127        }
128
129        impl<'de, M> $decode<'de, M> for Cow<'de, $ty> {
130            #[inline]
131            fn $decode_fn<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
132            where
133                D: Decoder<'de, Mode = M>,
134            {
135                struct Visitor;
136
137                impl<'de, C> UnsizedVisitor<'de, C, $source> for Visitor
138                where
139                    C: ?Sized + Context,
140                {
141                    type Ok = Cow<'de, $ty>;
142
143                    #[inline]
144                    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145                        write!(f, "a string")
146                    }
147
148                    #[inline]
149                    fn visit_owned(
150                        self,
151                        $cx: &C,
152                        $owned: <$source as ToOwned>::Owned,
153                    ) -> Result<Self::Ok, C::Error> {
154                        Ok($owned_expr)
155                    }
156
157                    #[inline]
158                    fn visit_borrowed(
159                        self,
160                        $cx: &C,
161                        $borrowed: &'de $source,
162                    ) -> Result<Self::Ok, C::Error> {
163                        Ok($borrowed_expr)
164                    }
165
166                    #[inline]
167                    fn visit_ref(
168                        self,
169                        $cx: &C,
170                        $reference: &$source,
171                    ) -> Result<Self::Ok, C::Error> {
172                        Ok($reference_expr)
173                    }
174                }
175
176                decoder.$decode_method(Visitor)
177            }
178        }
179    };
180}
181
182cow! {
183    Encode::encode,
184    Decode::decode,
185    str, str, decode_string, _,
186    |owned| Cow::Owned(owned),
187    |borrowed| Cow::Borrowed(borrowed),
188    |reference| Cow::Owned(reference.to_owned())
189}
190
191cow! {
192    Encode::encode,
193    Decode::decode,
194    CStr, [u8], decode_bytes, cx,
195    |owned| Cow::Owned(CString::from_vec_with_nul(owned).map_err(cx.map())?),
196    |borrowed| Cow::Borrowed(CStr::from_bytes_with_nul(borrowed).map_err(cx.map())?),
197    |reference| Cow::Owned(CStr::from_bytes_with_nul(reference).map_err(cx.map())?.to_owned())
198}
199
200cow! {
201    EncodeBytes::encode_bytes,
202    DecodeBytes::decode_bytes,
203    [u8], [u8], decode_bytes, _,
204    |owned| Cow::Owned(owned),
205    |borrowed| Cow::Borrowed(borrowed),
206    |reference| Cow::Owned(reference.to_owned())
207}
208
209macro_rules! sequence {
210    (
211        $(#[$($meta:meta)*])*
212        $cx:ident,
213        $ty:ident <T $(: $trait0:ident $(+ $trait:ident)*)? $(, $extra:ident: $extra_bound0:ident $(+ $extra_bound:ident)*)*>,
214        $insert:ident,
215        $access:ident,
216        $factory:expr
217    ) => {
218        $(#[$($meta)*])*
219        impl<M, T $(, $extra)*> Encode<M> for $ty<T $(, $extra)*>
220        where
221            T: Encode<M>,
222            $($extra: $extra_bound0 $(+ $extra_bound)*),*
223        {
224            #[inline]
225            fn encode<E>(&self, $cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
226            where
227                E: Encoder<Mode = M>,
228            {
229                let hint = SequenceHint::with_size(self.len());
230
231                encoder.encode_sequence_fn(&hint, |seq| {
232                    let mut index = 0;
233
234                    for value in self {
235                        $cx.enter_sequence_index(index);
236                        seq.push(value)?;
237                        $cx.leave_sequence_index();
238                        index = index.wrapping_add(1);
239                    }
240
241                    Ok(())
242                })
243            }
244        }
245
246        $(#[$($meta)*])*
247        impl<'de, M, T $(, $extra)*> Decode<'de, M> for $ty<T $(, $extra)*>
248        where
249            T: Decode<'de, M> $(+ $trait0 $(+ $trait)*)*,
250            $($extra: $extra_bound0 $(+ $extra_bound)*),*
251        {
252            #[inline]
253            fn decode<D>($cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
254            where
255                D: Decoder<'de, Mode = M>,
256            {
257                decoder.decode_sequence(|$access| {
258                    let mut out = $factory;
259
260                    let mut index = 0;
261
262                    while let Some(value) = $access.try_decode_next()? {
263                        $cx.enter_sequence_index(index);
264                        out.$insert(T::decode($cx, value)?);
265                        $cx.leave_sequence_index();
266                        index = index.wrapping_add(1);
267                    }
268
269                    Ok(out)
270                })
271            }
272        }
273
274        $(#[$($meta)*])*
275        impl<M, T $(, $extra)*> EncodePacked<M> for $ty<T $(, $extra)*>
276        where
277            T: Encode<M>,
278            $($extra: $extra_bound0 $(+ $extra_bound)*),*
279        {
280            #[inline]
281            fn encode_packed<E>(&self, $cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
282            where
283                E: Encoder<Mode = M>,
284            {
285                encoder.encode_pack_fn(|pack| {
286                    let mut index = 0;
287
288                    for value in self {
289                        $cx.enter_sequence_index(index);
290                        pack.push(value)?;
291                        $cx.leave_sequence_index();
292                        index = index.wrapping_add(1);
293                    }
294
295                    Ok(())
296                })
297            }
298        }
299    }
300}
301
302sequence!(
303    cx,
304    Vec<T>,
305    push,
306    seq,
307    Vec::with_capacity(size_hint::cautious(seq.size_hint()))
308);
309sequence!(
310    cx,
311    VecDeque<T>,
312    push_back,
313    seq,
314    VecDeque::with_capacity(size_hint::cautious(seq.size_hint()))
315);
316sequence!(cx, BTreeSet<T: Ord>, insert, seq, BTreeSet::new());
317sequence!(
318    #[cfg(feature = "std")]
319    #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
320    cx,
321    HashSet<T: Eq + Hash, S: BuildHasher + Default>,
322    insert,
323    seq,
324    HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default())
325);
326sequence!(
327    cx,
328    BinaryHeap<T: Ord>,
329    push,
330    seq,
331    BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint()))
332);
333
334macro_rules! map {
335    (
336        $(#[$($meta:meta)*])*
337        $cx:ident,
338        $ty:ident<K $(: $key_bound0:ident $(+ $key_bound:ident)*)?, V $(, $extra:ident: $extra_bound0:ident $(+ $extra_bound:ident)*)*>,
339        $access:ident,
340        $with_capacity:expr
341    ) => {
342        $(#[$($meta)*])*
343        impl<'de, M, K, V $(, $extra)*> Encode<M> for $ty<K, V $(, $extra)*>
344        where
345            K: Encode<M>,
346            V: Encode<M>,
347            $($extra: $extra_bound0 $(+ $extra_bound)*),*
348        {
349            #[inline]
350            fn encode<E>(&self, $cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
351            where
352                E: Encoder<Mode = M>,
353            {
354                let hint = MapHint::with_size(self.len());
355
356                encoder.encode_map_fn(&hint, |map| {
357                    for (k, v) in self {
358                        map.insert_entry(k, v)?;
359                    }
360
361                    Ok(())
362                })
363            }
364        }
365
366        $(#[$($meta)*])*
367        impl<'de, M, K, V $(, $extra)*> EncodeTrace<M> for $ty<K, V $(, $extra)*>
368        where
369            K: fmt::Display + Encode<M>,
370            V: Encode<M>,
371            $($extra: $extra_bound0 $(+ $extra_bound)*),*
372        {
373            #[inline]
374            fn trace_encode<E>(&self, $cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
375            where
376                E: Encoder<Mode = M>,
377            {
378                let hint = MapHint::with_size(self.len());
379
380                encoder.encode_map_fn(&hint, |map| {
381                    for (k, v) in self {
382                        $cx.enter_map_key(k);
383                        map.encode_entry_fn(|entry| {
384                            entry.encode_key()?.encode(k)?;
385                            entry.encode_value()?.encode(v)?;
386                            Ok(())
387                        })?;
388                        $cx.leave_map_key();
389                    }
390
391                    Ok(())
392                })
393            }
394        }
395
396        $(#[$($meta)*])*
397        impl<'de, K, V, M $(, $extra)*> Decode<'de, M> for $ty<K, V $(, $extra)*>
398        where
399            K: Decode<'de, M> $(+ $key_bound0 $(+ $key_bound)*)*,
400            V: Decode<'de, M>,
401            $($extra: $extra_bound0 $(+ $extra_bound)*),*
402        {
403            #[inline]
404            fn decode<D>($cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
405            where
406                D: Decoder<'de, Mode = M>,
407            {
408                decoder.decode_map(|$access| {
409                    let mut out = $with_capacity;
410
411                    while let Some((key, value)) = $access.entry()? {
412                        out.insert(key, value);
413                    }
414
415                    Ok(out)
416                })
417            }
418        }
419
420        $(#[$($meta)*])*
421        impl<'de, K, V, M $(, $extra)*> DecodeTrace<'de, M> for $ty<K, V $(, $extra)*>
422        where
423            K: fmt::Display + Decode<'de, M> $(+ $key_bound0 $(+ $key_bound)*)*,
424            V: Decode<'de, M>,
425            $($extra: $extra_bound0 $(+ $extra_bound)*),*
426        {
427            #[inline]
428            fn trace_decode<D>($cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
429            where
430                D: Decoder<'de, Mode = M>,
431            {
432                decoder.decode_map(|$access| {
433                    let mut out = $with_capacity;
434
435                    while let Some(mut entry) = $access.decode_entry()? {
436                        let key = entry.decode_key()?.decode()?;
437                        $cx.enter_map_key(&key);
438                        let value = entry.decode_value()?.decode()?;
439                        out.insert(key, value);
440                        $cx.leave_map_key();
441                    }
442
443                    Ok(out)
444                })
445            }
446        }
447    }
448}
449
450map!(_cx, BTreeMap<K: Ord, V>, map, BTreeMap::new());
451
452map!(
453    #[cfg(feature = "std")]
454    #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
455    _cx,
456    HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
457    map,
458    HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default())
459);
460
461impl<M> Encode<M> for CString {
462    #[inline]
463    fn encode<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
464    where
465        E: Encoder,
466    {
467        encoder.encode_bytes(self.to_bytes_with_nul())
468    }
469}
470
471impl<'de, M> Decode<'de, M> for CString {
472    #[inline]
473    fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
474    where
475        D: Decoder<'de>,
476    {
477        struct Visitor;
478
479        impl<'de, C> UnsizedVisitor<'de, C, [u8]> for Visitor
480        where
481            C: ?Sized + Context,
482        {
483            type Ok = CString;
484
485            #[inline]
486            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487                write!(f, "a cstring")
488            }
489
490            #[inline]
491            fn visit_owned(self, cx: &C, value: Vec<u8>) -> Result<Self::Ok, C::Error> {
492                CString::from_vec_with_nul(value).map_err(cx.map())
493            }
494
495            #[inline]
496            fn visit_borrowed(self, cx: &C, bytes: &'de [u8]) -> Result<Self::Ok, C::Error> {
497                self.visit_ref(cx, bytes)
498            }
499
500            #[inline]
501            fn visit_ref(self, cx: &C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
502                Ok(CStr::from_bytes_with_nul(bytes)
503                    .map_err(cx.map())?
504                    .to_owned())
505            }
506        }
507
508        decoder.decode_bytes(Visitor)
509    }
510}
511
512macro_rules! smart_pointer {
513    ($($ty:ident),* $(,)?) => {
514        $(
515            impl<M, T> Encode<M> for $ty<T>
516            where
517                T: ?Sized + Encode<M>,
518            {
519                #[inline]
520                fn encode<E>(&self, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
521                where
522                    E: Encoder<Mode = M>,
523                {
524                    self.as_ref().encode(cx, encoder)
525                }
526            }
527
528            impl<'de, M, T> Decode<'de, M> for $ty<T>
529            where
530                T: Decode<'de, M>,
531            {
532                #[inline]
533                fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
534                where
535                    D: Decoder<'de, Mode = M>,
536                {
537                    Ok($ty::new(decoder.decode()?))
538                }
539            }
540
541            impl<'de, M> DecodeBytes<'de, M> for $ty<[u8]> {
542                #[inline]
543                fn decode_bytes<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
544                where
545                    D: Decoder<'de, Mode = M>,
546                {
547                    Ok($ty::from(<Vec<u8>>::decode_bytes(cx, decoder)?))
548                }
549            }
550
551            impl<'de, M> Decode<'de, M> for $ty<CStr> {
552                #[inline]
553                fn decode<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
554                where
555                    D: Decoder<'de, Mode = M>,
556                {
557                    Ok($ty::from(CString::decode(cx, decoder)?))
558                }
559            }
560
561            #[cfg(all(feature = "std", any(unix, windows)))]
562            #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
563            impl<'de, M> Decode<'de, M> for $ty<Path> where PlatformTag: Decode<'de, M> {
564                #[inline]
565                fn decode<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
566                where
567                    D: Decoder<'de, Mode = M>,
568                {
569                    Ok($ty::from(PathBuf::decode(cx, decoder)?))
570                }
571            }
572
573            #[cfg(all(feature = "std", any(unix, windows)))]
574            #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
575            impl<'de, M> Decode<'de, M> for $ty<OsStr> where PlatformTag: Decode<'de, M> {
576                #[inline]
577                fn decode<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
578                where
579                    D: Decoder<'de, Mode = M>,
580                {
581                    Ok($ty::from(OsString::decode(cx, decoder)?))
582                }
583            }
584        )*
585    };
586}
587
588smart_pointer!(Box, Arc, Rc);
589
590#[cfg(all(feature = "std", any(unix, windows)))]
591#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
592impl<M> Encode<M> for OsStr
593where
594    PlatformTag: Encode<M>,
595{
596    #[cfg(unix)]
597    #[inline]
598    fn encode<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
599    where
600        E: Encoder<Mode = M>,
601    {
602        use std::os::unix::ffi::OsStrExt;
603
604        use crate::en::VariantEncoder;
605
606        encoder.encode_variant_fn(|variant| {
607            variant.encode_tag()?.encode(PlatformTag::Unix)?;
608            variant.encode_data()?.encode_bytes(self.as_bytes())?;
609            Ok(())
610        })
611    }
612
613    #[cfg(windows)]
614    #[inline]
615    fn encode<E>(&self, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
616    where
617        E: Encoder<Mode = M>,
618    {
619        use std::os::windows::ffi::OsStrExt;
620
621        use crate::alloc::{Allocator, RawVec};
622        use crate::en::VariantEncoder;
623
624        encoder.encode_variant_fn(|variant| {
625            let mut buf = cx.alloc().new_raw_vec::<u8>();
626            let mut len = 0;
627
628            for w in self.encode_wide() {
629                let bytes = w.to_le_bytes();
630
631                if !buf.resize(len, bytes.len()) {
632                    return Err(cx.message("Allocation failed"));
633                }
634
635                // SAFETY: We've just resized the above buffer.
636                unsafe {
637                    buf.as_mut_ptr()
638                        .add(len)
639                        .copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
640                }
641
642                len += bytes.len();
643            }
644
645            // SAFETY: Slice does not outlive the buffer it references.
646            let bytes = unsafe { core::slice::from_raw_parts(buf.as_ptr(), len) };
647
648            variant.encode_tag()?.encode(PlatformTag::Windows)?;
649            variant.encode_data()?.encode_bytes(bytes)?;
650            Ok(())
651        })
652    }
653}
654
655#[cfg(all(feature = "std", any(unix, windows)))]
656#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
657impl<M> Encode<M> for OsString
658where
659    PlatformTag: Encode<M>,
660{
661    #[inline]
662    fn encode<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
663    where
664        E: Encoder<Mode = M>,
665    {
666        encoder.encode(self.as_os_str())
667    }
668}
669
670#[cfg(all(feature = "std", any(unix, windows)))]
671#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
672impl<'de, M> Decode<'de, M> for OsString
673where
674    PlatformTag: Decode<'de, M>,
675{
676    #[inline]
677    fn decode<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
678    where
679        D: Decoder<'de, Mode = M>,
680    {
681        use crate::de::VariantDecoder;
682
683        decoder.decode_variant(|variant| {
684            let tag = variant.decode_tag()?.decode::<PlatformTag>()?;
685
686            match tag {
687                #[cfg(not(unix))]
688                PlatformTag::Unix => Err(cx.message("Unsupported OsString::Unix variant")),
689                #[cfg(unix)]
690                PlatformTag::Unix => {
691                    use std::os::unix::ffi::OsStringExt;
692                    Ok(OsString::from_vec(variant.decode_value()?.decode()?))
693                }
694                #[cfg(not(windows))]
695                PlatformTag::Windows => Err(cx.message("Unsupported OsString::Windows variant")),
696                #[cfg(windows)]
697                PlatformTag::Windows => {
698                    use std::os::windows::ffi::OsStringExt;
699
700                    struct Visitor;
701
702                    impl<'de, C> UnsizedVisitor<'de, C, [u8]> for Visitor
703                    where
704                        C: ?Sized + Context,
705                    {
706                        type Ok = OsString;
707
708                        #[inline]
709                        fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
710                            write!(f, "a literal byte reference")
711                        }
712
713                        #[inline]
714                        fn visit_ref(self, _: &C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
715                            let mut buf = Vec::with_capacity(bytes.len() / 2);
716
717                            for pair in bytes.chunks_exact(2) {
718                                let &[a, b] = pair else {
719                                    continue;
720                                };
721
722                                buf.push(u16::from_le_bytes([a, b]));
723                            }
724
725                            Ok(OsString::from_wide(&buf))
726                        }
727                    }
728
729                    variant.decode_value()?.decode_bytes(Visitor)
730                }
731            }
732        })
733    }
734}
735
736#[cfg(all(feature = "std", any(unix, windows)))]
737#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
738impl<M> Encode<M> for Path
739where
740    PlatformTag: Encode<M>,
741{
742    #[inline]
743    fn encode<E>(&self, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
744    where
745        E: Encoder<Mode = M>,
746    {
747        self.as_os_str().encode(cx, encoder)
748    }
749}
750
751#[cfg(all(feature = "std", any(unix, windows)))]
752#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
753impl<M> Encode<M> for PathBuf
754where
755    PlatformTag: Encode<M>,
756{
757    #[inline]
758    fn encode<E>(&self, cx: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
759    where
760        E: Encoder<Mode = M>,
761    {
762        self.as_path().encode(cx, encoder)
763    }
764}
765
766#[cfg(all(feature = "std", any(unix, windows)))]
767#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
768impl<'de, M> Decode<'de, M> for PathBuf
769where
770    PlatformTag: Decode<'de, M>,
771{
772    #[inline]
773    fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
774    where
775        D: Decoder<'de, Mode = M>,
776    {
777        Ok(PathBuf::from(decoder.decode::<OsString>()?))
778    }
779}
780
781impl<M> EncodeBytes<M> for Vec<u8> {
782    #[inline]
783    fn encode_bytes<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
784    where
785        E: Encoder<Mode = M>,
786    {
787        encoder.encode_bytes(self.as_slice())
788    }
789}
790
791impl<M> EncodeBytes<M> for Box<[u8]> {
792    #[inline]
793    fn encode_bytes<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
794    where
795        E: Encoder<Mode = M>,
796    {
797        encoder.encode_bytes(self.as_ref())
798    }
799}
800
801impl<'de, M> DecodeBytes<'de, M> for Vec<u8> {
802    #[inline]
803    fn decode_bytes<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
804    where
805        D: Decoder<'de, Mode = M>,
806    {
807        struct Visitor;
808
809        impl<'de, C> UnsizedVisitor<'de, C, [u8]> for Visitor
810        where
811            C: ?Sized + Context,
812        {
813            type Ok = Vec<u8>;
814
815            #[inline]
816            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817                write!(f, "bytes")
818            }
819
820            #[inline]
821            fn visit_borrowed(self, _: &C, bytes: &'de [u8]) -> Result<Self::Ok, C::Error> {
822                Ok(bytes.to_vec())
823            }
824
825            #[inline]
826            fn visit_ref(self, _: &C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
827                Ok(bytes.to_vec())
828            }
829        }
830
831        decoder.decode_bytes(Visitor)
832    }
833}
834
835impl<M> EncodeBytes<M> for VecDeque<u8> {
836    #[inline]
837    fn encode_bytes<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
838    where
839        E: Encoder<Mode = M>,
840    {
841        let (first, second) = self.as_slices();
842        encoder.encode_bytes_vectored(self.len(), &[first, second])
843    }
844}
845
846impl<'de, M> DecodeBytes<'de, M> for VecDeque<u8> {
847    #[inline]
848    fn decode_bytes<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
849    where
850        D: Decoder<'de, Mode = M>,
851    {
852        Ok(VecDeque::from(<Vec<u8>>::decode_bytes(cx, decoder)?))
853    }
854}