Skip to main content

deser_core/adapters/bytes/
impls.rs

1//! The adapters for bytes.
2use alloc::borrow::Cow;
3use alloc::format;
4use alloc::vec::Vec;
5use core::marker::PhantomData;
6
7use crate::BytesFormat;
8use crate::State;
9use crate::adapters::bytes::BytesEncoding;
10use crate::de::{Deserialize, Sink, SinkHandle, default_atom};
11use crate::error::{Error, ErrorKind};
12use crate::event::{Atom, Bytes, ContainerShape};
13use crate::ser::{Begin, Emit, Serialize};
14
15mod sealed {
16    use super::*;
17
18    pub trait BytesBufImpl: Sized + Send + Sync {
19        fn bytes(&self) -> &[u8];
20        fn from_vec(bytes: Vec<u8>) -> Result<Self, Error>;
21        fn deserialize_into<'a, 'de>(
22            out: &'a mut Option<Self>,
23            state: &mut State,
24        ) -> SinkHandle<'a, 'de>;
25        fn expecting() -> Cow<'static, str>;
26    }
27
28    pub trait BytesFallbackFormatImpl: Send + Sync + 'static {
29        const FORMAT: BytesFormat;
30        fn deserialize_into<'a, 'de, T: BytesBufImpl>(
31            out: &'a mut Option<T>,
32            state: &mut State,
33        ) -> SinkHandle<'a, 'de>;
34        fn expecting<T: BytesBufImpl>() -> Cow<'static, str>;
35    }
36}
37
38pub(crate) use self::sealed::BytesBufImpl;
39use self::sealed::BytesFallbackFormatImpl;
40
41/// The types that the bytes adapters support.
42///
43/// These are `Vec<u8>`, `[u8; N]` and `Cow<[u8]>`.  With the features of
44/// the same name also `bytes::Bytes`, `bytes::BytesMut`,
45/// `bstr::BString`, `smallvec::SmallVec<[u8; N]>` and
46/// `arrayvec::ArrayVec<u8, N>`.  The trait is sealed, it cannot be
47/// implemented outside of deser.
48pub trait BytesBuf: BytesBufImpl {}
49
50impl<T: BytesBufImpl> BytesBuf for T {}
51
52impl BytesBufImpl for Vec<u8> {
53    #[inline]
54    fn bytes(&self) -> &[u8] {
55        self
56    }
57
58    #[inline]
59    fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
60        Ok(bytes)
61    }
62
63    #[inline]
64    fn deserialize_into<'a, 'de>(
65        out: &'a mut Option<Self>,
66        state: &mut State,
67    ) -> SinkHandle<'a, 'de> {
68        <Self as Deserialize<'de>>::deserialize_into(out, state)
69    }
70
71    fn expecting() -> Cow<'static, str> {
72        <Self as Deserialize<'static>>::expecting()
73    }
74}
75
76impl<const N: usize> BytesBufImpl for [u8; N] {
77    #[inline]
78    fn bytes(&self) -> &[u8] {
79        self
80    }
81
82    fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
83        bytes
84            .try_into()
85            .map_err(|_| Error::new(ErrorKind::WrongLength, "byte array of wrong length"))
86    }
87
88    #[inline]
89    fn deserialize_into<'a, 'de>(
90        out: &'a mut Option<Self>,
91        state: &mut State,
92    ) -> SinkHandle<'a, 'de> {
93        <Self as Deserialize<'de>>::deserialize_into(out, state)
94    }
95
96    fn expecting() -> Cow<'static, str> {
97        <Self as Deserialize<'static>>::expecting()
98    }
99}
100
101impl<'c> BytesBufImpl for Cow<'c, [u8]> {
102    #[inline]
103    fn bytes(&self) -> &[u8] {
104        self
105    }
106
107    #[inline]
108    fn from_vec(bytes: Vec<u8>) -> Result<Self, Error> {
109        Ok(Cow::Owned(bytes))
110    }
111
112    #[inline]
113    fn deserialize_into<'a, 'de>(
114        out: &'a mut Option<Self>,
115        state: &mut State,
116    ) -> SinkHandle<'a, 'de> {
117        <Self as Deserialize<'de>>::deserialize_into(out, state)
118    }
119
120    fn expecting() -> Cow<'static, str> {
121        <Self as Deserialize<'static>>::expecting()
122    }
123}
124
125/// The representations that [`BytesFallback`] supports.
126///
127/// These are all [encodings](BytesEncoding) and [`IntSeq`].  The trait is
128/// sealed, it cannot be implemented outside of deser.  New encodings are
129/// added by implementing [`BytesEncoding`].
130pub trait BytesFallbackFormat: BytesFallbackFormatImpl {}
131
132impl<F: BytesFallbackFormatImpl> BytesFallbackFormat for F {}
133
134impl<E: BytesEncoding> BytesFallbackFormatImpl for E {
135    const FORMAT: BytesFormat = BytesFormat::encoded::<E>();
136
137    #[inline]
138    fn deserialize_into<'a, 'de, T: BytesBufImpl>(
139        out: &'a mut Option<T>,
140        state: &mut State,
141    ) -> SinkHandle<'a, 'de> {
142        encoded_handle::<T, E>(out, state)
143    }
144
145    fn expecting<T: BytesBufImpl>() -> Cow<'static, str> {
146        encoded_expecting::<E>()
147    }
148}
149
150/// Represents bytes as sequences of integers.
151///
152/// This is only used with [`BytesFallback`], `BytesFallback<IntSeq>` writes
153/// bytes as sequences of integers in formats without native bytes (like
154/// `serde_json`).  It corresponds to [`BytesFormat::SEQ`].
155pub struct IntSeq;
156
157impl BytesFallbackFormatImpl for IntSeq {
158    const FORMAT: BytesFormat = BytesFormat::SEQ;
159
160    #[inline]
161    fn deserialize_into<'a, 'de, T: BytesBufImpl>(
162        out: &'a mut Option<T>,
163        state: &mut State,
164    ) -> SinkHandle<'a, 'de> {
165        // bytes accept sequences of integers anyways
166        T::deserialize_into(out, state)
167    }
168
169    fn expecting<T: BytesBufImpl>() -> Cow<'static, str> {
170        T::expecting()
171    }
172}
173
174/// What bytes with an encoding expect.
175pub(crate) fn encoded_expecting<E: BytesEncoding>() -> Cow<'static, str> {
176    Cow::Owned(format!("bytes or {} string", E::NAME))
177}
178
179/// Deserializes bytes which are either native bytes or encoded strings.
180struct EncodedSink<'a, T, E> {
181    out: &'a mut Option<T>,
182    _marker: PhantomData<fn() -> E>,
183}
184
185impl<'a, 'de, T: BytesBufImpl, E: BytesEncoding> Sink<'de> for EncodedSink<'a, T, E> {
186    fn expecting(&self) -> Cow<'_, str> {
187        encoded_expecting::<E>()
188    }
189
190    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
191        let bytes = match atom {
192            Atom::Bytes(value) => value.into_data().into_owned(),
193            Atom::Str(value) => E::decode(&value)?,
194            other => return default_atom(self, other, state),
195        };
196        *self.out = Some(T::from_vec(bytes)?);
197        Ok(())
198    }
199}
200
201#[inline]
202pub(crate) fn encoded_handle<'a, 'de, T: BytesBufImpl, E: BytesEncoding>(
203    out: &'a mut Option<T>,
204    state: &mut State,
205) -> SinkHandle<'a, 'de> {
206    SinkHandle::arena(
207        EncodedSink::<T, E> {
208            out,
209            _marker: PhantomData,
210        },
211        state,
212    )
213}
214
215/// Makes the encodings adapters which represent bytes as strings in all
216/// formats and accept strings in the encoding and native bytes.
217///
218/// The impls are for the concrete types rather than all [`BytesBuf`]s as
219/// otherwise they would conflict with the impls for `Box<U>`.
220macro_rules! encoding_adapter {
221    ($([$($gen:tt)*] $ty:ty),* $(,)?) => {
222        $(
223            impl<$($gen)* E: $crate::adapters::BytesEncoding> $crate::ser::Serialize<$ty> for E {
224                fn serialize<'a>(
225                    value: &'a $ty,
226                    _state: &mut $crate::State,
227                ) -> Result<$crate::ser::Emit<'a>, $crate::Error> {
228                    let mut rv = alloc::string::String::new();
229                    E::encode(
230                        $crate::adapters::bytes::BytesBufImpl::bytes(value),
231                        &mut rv,
232                    );
233                    Ok($crate::ser::Emit::Atom($crate::Atom::Str($crate::Text::owned(rv))))
234                }
235
236                // rustdoc shows the hidden method in blanket impls
237                #[doc(hidden)]
238                #[inline]
239                fn __private_begin<'a>(
240                    value: &'a $ty,
241                    state: &mut $crate::State,
242                ) -> Result<$crate::ser::Begin<'a>, $crate::Error> {
243                    Ok($crate::ser::Begin::emit(
244                        Self::serialize(value, state)?,
245                        $crate::ContainerShape::new(),
246                        false,
247                    ))
248                }
249            }
250
251            impl<'de, $($gen)* E: $crate::adapters::BytesEncoding>
252                $crate::de::Deserialize<'de, $ty> for E
253            {
254                #[inline]
255                fn deserialize_into<'a>(
256                    out: &'a mut Option<$ty>, state: &mut $crate::State) -> $crate::de::SinkHandle<'a, 'de> {
257                    $crate::adapters::bytes::encoded_handle::<$ty, E>(out, state)
258                }
259
260                fn expecting() -> alloc::borrow::Cow<'static, str> {
261                    $crate::adapters::bytes::encoded_expecting::<E>()
262                }
263            }
264        )*
265    };
266}
267
268// also used for the byte buffers of other crates
269#[allow(unused_imports)]
270pub(crate) use encoding_adapter;
271
272encoding_adapter!(
273    [] Vec<u8>,
274    [const N: usize,] [u8; N],
275    ['c,] Cow<'c, [u8]>,
276);
277
278/// Represents bytes as bytes, with a fallback for formats without native bytes.
279///
280/// The bytes are serialized as bytes which carry the format `F` as
281/// fallback (see [`Bytes::fallback`](crate::Bytes::fallback)).  Formats with native bytes (like CBOR)
282/// write them as bytes, formats without native bytes (like JSON and TOML)
283/// write them in `F`: strings in an [encoding](BytesEncoding) or sequences
284/// of integers for [`IntSeq`].  When deserializing native bytes and the
285/// representation of `F` are accepted.  It supports the types of
286/// [`BytesBuf`].
287///
288/// ```
289/// use deser::adapters::{Base64Url, BytesFallback, IntSeq};
290/// use deser::{Deserialize, Serialize};
291///
292/// #[derive(Serialize, Deserialize)]
293/// pub struct Blob {
294///     // URL-safe base64 in JSON and TOML, bytes in CBOR
295///     #[deser(as = BytesFallback<Base64Url>)]
296///     sha1: [u8; 20],
297///     #[deser(as = Option<BytesFallback<Base64Url>>)]
298///     signature: Option<Vec<u8>>,
299///     // `[1, 2]` in JSON and TOML, bytes in CBOR
300///     #[deser(as = BytesFallback<IntSeq>)]
301///     legacy: Vec<u8>,
302/// }
303/// ```
304///
305/// To use an encoding in all formats, use the encoding as adapter (for
306/// instance `#[deser(as = Base64Url)]`).  To change the representation of all
307/// bytes, configure the format instead.
308pub struct BytesFallback<F>(PhantomData<fn() -> F>);
309
310impl<T: BytesBuf, F: BytesFallbackFormat> Serialize<T> for BytesFallback<F> {
311    #[inline]
312    fn serialize<'a>(value: &'a T, _state: &mut State) -> Result<Emit<'a>, Error> {
313        let mut bytes = Bytes::borrowed(value.bytes());
314        bytes.fallback = Some(const { &F::FORMAT });
315        Ok(Emit::Atom(Atom::Bytes(bytes)))
316    }
317
318    #[inline]
319    fn __private_begin<'a>(value: &'a T, state: &mut State) -> Result<Begin<'a>, Error> {
320        Ok(Begin::emit(
321            Self::serialize(value, state)?,
322            ContainerShape::new(),
323            false,
324        ))
325    }
326}
327
328impl<'de, T: BytesBuf, F: BytesFallbackFormat> Deserialize<'de, T> for BytesFallback<F> {
329    #[inline]
330    fn deserialize_into<'out>(
331        out: &'out mut Option<T>,
332        state: &mut State,
333    ) -> SinkHandle<'out, 'de> {
334        F::deserialize_into(out, state)
335    }
336
337    fn expecting() -> Cow<'static, str> {
338        F::expecting::<T>()
339    }
340}