serdapt/
bytes.rs

1// Copyright (c) 2024 Stephane Raux. Distributed under the 0BSD license.
2
3use crate::{DeserializeWith, SerializeWith};
4#[cfg(feature = "alloc")]
5use alloc::{borrow::Cow, boxed::Box, rc::Rc, string::String, vec::Vec};
6use core::{fmt, marker::PhantomData};
7use serde::{Deserializer, Serializer, de::Visitor};
8
9/// Adapter for contiguous byte sequences
10///
11/// If a type is not supported by this adapter and is convertible from `Vec<u8>`, the [`ByteVec`]
12/// adapter should be used instead.
13///
14/// This allows optimized handling of byte sequences when serializing. This is similar to
15/// [`serde_bytes`](https://docs.rs/serde_bytes). Practically, this adapter allows serialization of
16/// bytes to go through [`Serializer::serialize_bytes`] and deserialization through
17/// [`Deserializer::deserialize_bytes`] or [`Deserializer::deserialize_byte_buf`].
18///
19/// This adapter always serializes as a serde variable-length byte sequence, even if the collection
20/// type to serialize has a statically known length.
21///
22/// # Example
23/// ```
24/// # #[cfg(feature = "std")] {
25/// use serde::{Deserialize, Serialize};
26///
27/// #[derive(Deserialize, Serialize)]
28/// struct Foo {
29///     #[serde(with = "serdapt::Bytes")]
30///     bytes: Vec<u8>,
31/// }
32/// # }
33/// ```
34pub struct Bytes;
35
36impl Bytes {
37    /// Serializes value as bytes
38    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
39    where
40        T: ?Sized,
41        S: Serializer,
42        Self: SerializeWith<T>,
43    {
44        Self::serialize_with(value, serializer)
45    }
46
47    /// Deserializes value from bytes
48    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
49    where
50        D: Deserializer<'de>,
51        Self: DeserializeWith<'de, T>,
52    {
53        Self::deserialize_with(deserializer)
54    }
55}
56
57impl<T> SerializeWith<T> for Bytes
58where
59    T: AsRef<[u8]> + ?Sized,
60{
61    fn serialize_with<S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
62        serializer.serialize_bytes(value.as_ref())
63    }
64}
65
66#[cfg(feature = "alloc")]
67impl<'de> DeserializeWith<'de, Vec<u8>> for Bytes {
68    fn deserialize_with<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
69    where
70        D: Deserializer<'de>,
71    {
72        deserializer.deserialize_byte_buf(VecVisitor)
73    }
74}
75
76#[cfg(feature = "alloc")]
77impl<'de> DeserializeWith<'de, Box<[u8]>> for Bytes {
78    fn deserialize_with<D>(deserializer: D) -> Result<Box<[u8]>, D::Error>
79    where
80        D: Deserializer<'de>,
81    {
82        <Bytes as DeserializeWith<'de, Vec<u8>>>::deserialize_with(deserializer).map(Into::into)
83    }
84}
85
86#[cfg(feature = "alloc")]
87impl<'de> DeserializeWith<'de, Rc<[u8]>> for Bytes {
88    fn deserialize_with<D>(deserializer: D) -> Result<Rc<[u8]>, D::Error>
89    where
90        D: Deserializer<'de>,
91    {
92        <Bytes as DeserializeWith<'de, Vec<u8>>>::deserialize_with(deserializer).map(Into::into)
93    }
94}
95
96#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
97impl<'de> DeserializeWith<'de, alloc::sync::Arc<[u8]>> for Bytes {
98    fn deserialize_with<D>(deserializer: D) -> Result<alloc::sync::Arc<[u8]>, D::Error>
99    where
100        D: Deserializer<'de>,
101    {
102        <Bytes as DeserializeWith<'de, Vec<u8>>>::deserialize_with(deserializer).map(Into::into)
103    }
104}
105
106impl<'de, const N: usize> DeserializeWith<'de, [u8; N]> for Bytes {
107    fn deserialize_with<D>(deserializer: D) -> Result<[u8; N], D::Error>
108    where
109        D: Deserializer<'de>,
110    {
111        deserializer.deserialize_bytes(ArrayVisitor::<N>)
112    }
113}
114
115impl<'de: 'a, 'a> DeserializeWith<'de, &'a [u8]> for Bytes {
116    fn deserialize_with<D>(deserializer: D) -> Result<&'a [u8], D::Error>
117    where
118        D: Deserializer<'de>,
119    {
120        deserializer.deserialize_bytes(SliceVisitor::default())
121    }
122}
123
124impl<'de: 'a, 'a, const N: usize> DeserializeWith<'de, &'a [u8; N]> for Bytes {
125    fn deserialize_with<D>(deserializer: D) -> Result<&'a [u8; N], D::Error>
126    where
127        D: Deserializer<'de>,
128    {
129        let bytes = deserializer.deserialize_bytes(SliceVisitor::default())?;
130        bytes
131            .try_into()
132            .map_err(|_| serde::de::Error::invalid_length(bytes.len(), &ArrayVisitor::<N>))
133    }
134}
135
136#[cfg(feature = "alloc")]
137impl<'de: 'a, 'a> DeserializeWith<'de, Cow<'a, [u8]>> for Bytes {
138    fn deserialize_with<D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error>
139    where
140        D: Deserializer<'de>,
141    {
142        deserializer.deserialize_bytes(CowVisitor::default())
143    }
144}
145
146#[cfg(feature = "alloc")]
147struct VecVisitor;
148
149#[cfg(feature = "alloc")]
150impl<'de> Visitor<'de> for VecVisitor {
151    type Value = Vec<u8>;
152
153    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        f.write_str("bytes")
155    }
156
157    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
158    where
159        E: serde::de::Error,
160    {
161        Ok(v)
162    }
163
164    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
165    where
166        E: serde::de::Error,
167    {
168        Ok(v.to_vec())
169    }
170
171    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
172    where
173        E: serde::de::Error,
174    {
175        Ok(v.into_bytes())
176    }
177
178    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
179    where
180        E: serde::de::Error,
181    {
182        Ok(v.as_bytes().to_vec())
183    }
184
185    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
186    where
187        A: serde::de::SeqAccess<'de>,
188    {
189        let mut bytes = Vec::with_capacity(seq.size_hint().unwrap_or(0).min(4096));
190        while let Some(b) = seq.next_element()? {
191            bytes.push(b);
192        }
193        Ok(bytes)
194    }
195}
196
197struct ArrayVisitor<const N: usize>;
198
199impl<'de, const N: usize> Visitor<'de> for ArrayVisitor<N> {
200    type Value = [u8; N];
201
202    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203        write!(f, "a byte array of {N} bytes")
204    }
205
206    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
207    where
208        E: serde::de::Error,
209    {
210        v.try_into().map_err(|_| E::invalid_length(v.len(), &self))
211    }
212
213    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
214    where
215        E: serde::de::Error,
216    {
217        self.visit_bytes(v.as_bytes())
218    }
219
220    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
221    where
222        A: serde::de::SeqAccess<'de>,
223    {
224        let mut bytes = [0u8; N];
225        bytes.iter_mut().enumerate().try_for_each(|(i, out)| {
226            *out = seq
227                .next_element()?
228                .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
229            Ok(())
230        })?;
231        Ok(bytes)
232    }
233}
234
235#[derive(Default)]
236struct SliceVisitor<'a>(PhantomData<&'a ()>);
237
238impl<'de: 'a, 'a> Visitor<'de> for SliceVisitor<'a> {
239    type Value = &'a [u8];
240
241    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242        f.write_str("bytes")
243    }
244
245    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
246    where
247        E: serde::de::Error,
248    {
249        Ok(v)
250    }
251
252    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
253    where
254        E: serde::de::Error,
255    {
256        Ok(v.as_bytes())
257    }
258}
259
260#[cfg(feature = "alloc")]
261#[derive(Default)]
262struct CowVisitor<'a>(PhantomData<&'a ()>);
263
264#[cfg(feature = "alloc")]
265impl<'de: 'a, 'a> Visitor<'de> for CowVisitor<'a> {
266    type Value = Cow<'a, [u8]>;
267
268    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        f.write_str("bytes")
270    }
271
272    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
273    where
274        E: serde::de::Error,
275    {
276        Ok(Cow::Borrowed(v))
277    }
278
279    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
280    where
281        E: serde::de::Error,
282    {
283        Ok(Cow::Owned(v))
284    }
285
286    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
287    where
288        E: serde::de::Error,
289    {
290        Ok(Cow::Owned(v.to_vec()))
291    }
292
293    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
294    where
295        E: serde::de::Error,
296    {
297        Ok(Cow::Borrowed(v.as_bytes()))
298    }
299
300    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
301    where
302        E: serde::de::Error,
303    {
304        Ok(Cow::Owned(v.into_bytes()))
305    }
306
307    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
308    where
309        E: serde::de::Error,
310    {
311        Ok(Cow::Owned(v.as_bytes().to_vec()))
312    }
313
314    fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
315    where
316        A: serde::de::SeqAccess<'de>,
317    {
318        VecVisitor.visit_seq(seq).map(Into::into)
319    }
320}
321
322/// Adapter for contiguous byte sequences that can be converted from `Vec<u8>`
323///
324/// [`Bytes`] is preferred if the type to serialize is an array. It avoids allocating a `Vec` when
325/// deserializing.
326///
327/// This allows optimized handling of byte sequences when serializing. This is similar to
328/// [`serde_bytes`](https://docs.rs/serde_bytes). Practically, this adapter allows serialization of
329/// bytes to go through [`Serializer::serialize_bytes`] and deserialization through
330/// [`Deserializer::deserialize_bytes`] or [`Deserializer::deserialize_byte_buf`].
331///
332/// This adapter always serializes as a serde variable-length byte sequence, even if the collection
333/// type to serialize has a statically known length.
334///
335/// # Example
336/// ```
337/// # #[cfg(feature = "std")] {
338/// use serde::{Deserialize, Serialize};
339///
340/// struct ByteWrapper(Vec<u8>);
341///
342/// impl From<Vec<u8>> for ByteWrapper {
343///     fn from(v: Vec<u8>) -> Self {
344///         Self(v)
345///     }
346/// }
347///
348/// impl AsRef<[u8]> for ByteWrapper {
349///     fn as_ref(&self) -> &[u8] {
350///         &self.0
351///     }
352/// }
353///
354/// #[derive(Deserialize, Serialize)]
355/// struct Foo {
356///     #[serde(with = "serdapt::ByteVec")]
357///     bytes: ByteWrapper,
358/// }
359/// # }
360/// ```
361#[cfg(feature = "alloc")]
362pub struct ByteVec;
363
364#[cfg(feature = "alloc")]
365impl ByteVec {
366    /// Serializes value as bytes
367    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
368    where
369        T: ?Sized,
370        S: Serializer,
371        Self: SerializeWith<T>,
372    {
373        Self::serialize_with(value, serializer)
374    }
375
376    /// Deserializes value from bytes
377    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
378    where
379        D: Deserializer<'de>,
380        Self: DeserializeWith<'de, T>,
381    {
382        Self::deserialize_with(deserializer)
383    }
384}
385
386#[cfg(feature = "alloc")]
387impl<T> SerializeWith<T> for ByteVec
388where
389    T: AsRef<[u8]> + ?Sized,
390{
391    fn serialize_with<S: Serializer>(value: &T, serializer: S) -> Result<S::Ok, S::Error> {
392        Bytes::serialize_with(value, serializer)
393    }
394}
395
396#[cfg(feature = "alloc")]
397impl<'de, T> DeserializeWith<'de, T> for ByteVec
398where
399    T: TryFrom<Vec<u8>>,
400    T::Error: core::fmt::Display,
401{
402    fn deserialize_with<D>(deserializer: D) -> Result<T, D::Error>
403    where
404        D: Deserializer<'de>,
405    {
406        let bytes: Vec<u8> = Bytes::deserialize_with(deserializer)?;
407        bytes.try_into().map_err(serde::de::Error::custom)
408    }
409}
410
411#[cfg(all(feature = "alloc", test))]
412mod tests {
413    use crate::test_utils::check_serialization;
414    use alloc::{borrow::Cow, boxed::Box, rc::Rc, vec, vec::Vec};
415    use core::fmt::Debug;
416    use serde::{Deserialize, Serialize};
417    use serde_json::json;
418
419    #[derive(Debug, Deserialize, PartialEq, Serialize)]
420    struct VecWrapper(#[serde(with = "crate::Bytes")] Vec<u8>);
421
422    #[test]
423    fn byte_vec_roundtrips() {
424        check_serialization(VecWrapper(vec![1, 2, 3]), json!([1, 2, 3]));
425    }
426
427    #[test]
428    fn empty_vec_roundtrips() {
429        check_serialization(VecWrapper(Vec::new()), json!([]));
430    }
431
432    #[derive(Debug, Deserialize, PartialEq, Serialize)]
433    struct SliceWrapper<'a>(#[serde(with = "crate::Bytes")] &'a [u8]);
434
435    #[test]
436    fn byte_slice_roundtrips() {
437        let original = SliceWrapper(b"foobar");
438        let serialized = bincode::serialize(&original).unwrap();
439        let deserialized = bincode::deserialize::<SliceWrapper<'_>>(&serialized).unwrap();
440        assert_eq!(deserialized, original);
441    }
442
443    #[derive(Debug, Deserialize, PartialEq, Serialize)]
444    struct BoxWrapper(#[serde(with = "crate::Bytes")] Box<[u8]>);
445
446    #[test]
447    fn boxed_bytes_roundtrip() {
448        check_serialization(BoxWrapper(vec![1, 2, 3].into()), json!([1, 2, 3]));
449    }
450
451    #[derive(Debug, Deserialize, PartialEq, Serialize)]
452    struct RcWrapper(#[serde(with = "crate::Bytes")] Rc<[u8]>);
453
454    #[test]
455    fn rced_bytes_roundtrip() {
456        check_serialization(RcWrapper(vec![1, 2, 3].into()), json!([1, 2, 3]));
457    }
458
459    #[cfg(target_has_atomic = "ptr")]
460    #[derive(Debug, Deserialize, PartialEq, Serialize)]
461    struct ArcWrapper(#[serde(with = "crate::Bytes")] alloc::sync::Arc<[u8]>);
462
463    #[cfg(target_has_atomic = "ptr")]
464    #[test]
465    fn arced_bytes_roundtrip() {
466        check_serialization(ArcWrapper(vec![1, 2, 3].into()), json!([1, 2, 3]));
467    }
468
469    #[derive(Debug, Deserialize, PartialEq, Serialize)]
470    struct ArrayWrapper<const N: usize>(#[serde(with = "crate::Bytes")] [u8; N]);
471
472    #[test]
473    fn byte_array_roundtrips() {
474        check_serialization(ArrayWrapper([1, 2, 3]), json!([1, 2, 3]));
475    }
476
477    #[test]
478    fn empty_byte_array_roundtrips() {
479        check_serialization(ArrayWrapper([]), json!([]));
480    }
481
482    #[derive(Debug, Deserialize, PartialEq, Serialize)]
483    struct RefArrayWrapper<'a, const N: usize>(
484        #[serde(borrow = "'a", with = "crate::Bytes")] &'a [u8; N],
485    );
486
487    #[test]
488    fn by_ref_byte_array_roundtrips() {
489        let original = RefArrayWrapper(b"foobar");
490        let serialized = bincode::serialize(&original).unwrap();
491        let deserialized = bincode::deserialize::<RefArrayWrapper<'_, 6>>(&serialized).unwrap();
492        assert_eq!(deserialized, original);
493    }
494
495    #[derive(Debug, Deserialize, PartialEq, Serialize)]
496    struct CowWrapper<'a>(#[serde(borrow = "'a", with = "crate::Bytes")] Cow<'a, [u8]>);
497
498    #[test]
499    fn cow_bytes_roundtrip() {
500        let original = CowWrapper(Cow::Borrowed(b"foobar"));
501        let serialized = bincode::serialize(&original).unwrap();
502        let deserialized = bincode::deserialize::<CowWrapper<'_>>(&serialized).unwrap();
503        assert_eq!(deserialized, original);
504        let CowWrapper(Cow::Borrowed(_)) = deserialized else {
505            panic!("Expected Cow::Borrowed");
506        };
507    }
508}