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