Skip to main content

pack_io/
traits.rs

1//! The [`Serialize`] and [`Deserialize`] traits.
2//!
3//! These are the seam between a Rust value and its wire-format bytes. They
4//! are generic over the [`Encode`] / [`Decode`] behaviour traits, so a single
5//! `impl Serialize` works through both the in-memory [`crate::Encoder`] and
6//! the streaming [`crate::IoEncoder`].
7//!
8//! The built-in primitive and collection implementations live in
9//! [`crate::impls`]. User-defined types either implement these traits
10//! directly or — with the `derive` feature on — derive them with
11//! `#[derive(pack_io::Serialize, pack_io::Deserialize)]`. The derive macro
12//! writes a sound, deterministic implementation for any struct or enum
13//! whose fields are themselves `Serialize` / `Deserialize`.
14
15use alloc::vec::Vec;
16
17use crate::codec::{Decode, Encode};
18use crate::error::Result;
19
20/// Types that know how to write themselves into any [`Encode`] sink.
21///
22/// The contract is: `serialize` appends the type's wire-format bytes to the
23/// encoder. It does **not** clear the encoder first — encoders are
24/// stream-shaped, and may already hold bytes from prior writes.
25///
26/// Implementors MUST be deterministic: for any two equal values `a` and `b`
27/// (in the type's `Eq` / `PartialEq` sense, or its semantic equivalent for
28/// types like `f64`), the bytes appended by `a.serialize(&mut enc)` MUST
29/// equal the bytes appended by `b.serialize(&mut enc)`.
30///
31/// # Examples
32///
33/// ```
34/// use pack_io::{Encode, Encoder, Result, Serialize};
35///
36/// struct Point { x: i32, y: i32 }
37///
38/// impl Serialize for Point {
39///     fn serialize<E: Encode + ?Sized>(&self, enc: &mut E) -> Result<()> {
40///         self.x.serialize(enc)?;
41///         self.y.serialize(enc)
42///     }
43/// }
44///
45/// let mut enc = Encoder::new();
46/// Point { x: 3, y: -7 }.serialize(&mut enc).unwrap();
47/// assert!(!enc.as_bytes().is_empty());
48/// ```
49pub trait Serialize {
50    /// Append the encoded bytes of `self` to `encoder`.
51    ///
52    /// # Errors
53    ///
54    /// Primitive impls in this crate are infallible on the in-memory
55    /// [`crate::Encoder`]. Streaming encoders (`IoEncoder<W>`) may surface
56    /// a [`crate::SerialError`] when the underlying `Write` errors. User
57    /// impls may also surface custom errors via [`crate::SerialError`].
58    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()>;
59
60    /// Append the encoded bytes of every element of `slice` to `encoder`.
61    ///
62    /// The default implementation calls [`Serialize::serialize`] once per
63    /// element. Types that can take advantage of a single bulk operation
64    /// — most importantly `u8`, which compiles down to a single
65    /// `extend_from_slice` / `Write::write_all` instead of N individual
66    /// pushes — override this to skip the per-element loop overhead.
67    ///
68    /// **This method is the seam that makes `Vec<u8>` encode at memcpy
69    /// speed without forcing `unsafe` or specialisation onto the public
70    /// trait surface.** The `[T]::serialize` impl calls
71    /// `T::serialize_slice(self, encoder)` rather than looping inline, so
72    /// any `Serialize` impl that overrides `serialize_slice` automatically
73    /// applies to every `&[T]`, `Vec<T>`, `[T; N]`, and `&[u8]`-shaped
74    /// payload that flows through it.
75    ///
76    /// # Errors
77    ///
78    /// Propagates any error returned by the per-element / bulk operation.
79    #[inline]
80    fn serialize_slice<E: Encode + ?Sized>(slice: &[Self], encoder: &mut E) -> Result<()>
81    where
82        Self: Sized,
83    {
84        for item in slice {
85            item.serialize(encoder)?;
86        }
87        Ok(())
88    }
89}
90
91/// Types that know how to read themselves from any [`Decode`] source.
92///
93/// The contract is: `deserialize` consumes exactly the bytes that a
94/// corresponding `Serialize` would have produced for the returned value, no
95/// more and no fewer. On any malformed input it MUST return an error and
96/// MUST NOT panic, allocate unboundedly, or read past the decoder's
97/// underlying source.
98///
99/// Round-trip invariant:
100/// `decode::<T>(&encode(&v)?)? == v` for every `v: T`.
101///
102/// # Examples
103///
104/// ```
105/// use pack_io::{Decode, Decoder, Deserialize, Result, encode};
106///
107/// struct Point { x: i32, y: i32 }
108///
109/// impl Deserialize for Point {
110///     fn deserialize<D: Decode + ?Sized>(dec: &mut D) -> Result<Self> {
111///         Ok(Point {
112///             x: i32::deserialize(dec)?,
113///             y: i32::deserialize(dec)?,
114///         })
115///     }
116/// }
117///
118/// # impl pack_io::Serialize for Point {
119/// #     fn serialize<E: pack_io::Encode + ?Sized>(&self, e: &mut E) -> Result<()> {
120/// #         self.x.serialize(e)?;
121/// #         self.y.serialize(e)
122/// #     }
123/// # }
124/// let bytes = encode(&Point { x: 3, y: -7 }).unwrap();
125/// let mut dec = Decoder::new(&bytes);
126/// let back = Point::deserialize(&mut dec).unwrap();
127/// assert_eq!((back.x, back.y), (3, -7));
128/// ```
129pub trait Deserialize: Sized {
130    /// Read a value of `Self` from the decoder, advancing its cursor.
131    ///
132    /// # Errors
133    ///
134    /// Any [`crate::SerialError`] the underlying byte reads surface
135    /// (truncated input, invalid length prefix, hostile varint, …).
136    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self>;
137
138    /// Read `count` consecutive `Self` values into a freshly-allocated `Vec`.
139    ///
140    /// The default implementation calls [`Deserialize::deserialize`] in a
141    /// loop. Types whose batch read can be done in a single bulk operation
142    /// — most importantly `u8`, which compiles down to a single
143    /// `Read::read_exact` instead of N individual byte reads — override
144    /// this for the memcpy-class fast path.
145    ///
146    /// **This method is the seam that makes `Vec<u8>` decode at memcpy
147    /// speed without forcing `unsafe` or specialisation onto the public
148    /// trait surface.** The `Vec<T>::deserialize` impl calls
149    /// `T::deserialize_many(decoder, len)` rather than looping inline.
150    ///
151    /// Implementations MUST cap any internal pre-allocation to bound
152    /// memory use against hostile length prefixes — the `count` argument
153    /// has already been validated against [`crate::Config::max_alloc`] by
154    /// the caller, but defensive implementations should still avoid
155    /// preallocating the full `count` for collections whose per-element
156    /// overhead is large.
157    ///
158    /// # Errors
159    ///
160    /// Propagates any error returned by the per-element / bulk read.
161    fn deserialize_many<D: Decode + ?Sized>(decoder: &mut D, count: usize) -> Result<Vec<Self>> {
162        // Cap initial capacity for the same reason the default `Vec<T>` impl
163        // does — hostile counts that pass `guard_element_count` but would
164        // blow the heap on a `Vec::with_capacity(count)` of large `T`.
165        let initial = count.min(4096);
166        let mut out = Vec::with_capacity(initial);
167        for _ in 0..count {
168            out.push(Self::deserialize(decoder)?);
169        }
170        Ok(out)
171    }
172}