Skip to main content

pack_io/
impls.rs

1//! `Serialize` / `Deserialize` implementations for primitive, container, and
2//! collection types.
3//!
4//! ## Wire format (full reference: [`docs/WIRE_FORMAT.md`])
5//!
6//! - `u8` / `i8` — one byte each (fixed). `i8` is two's-complement.
7//! - `u16` / `u32` / `u64` / `u128` / `usize` — LEB128 varint. `usize` is
8//!   encoded through `u64`; on a 32-bit target a decoded value outside
9//!   `usize::MAX` is rejected with [`SerialError::IntegerOutOfRange`].
10//! - `i16` / `i32` / `i64` / `i128` / `isize` — ZigZag mapping followed by
11//!   LEB128 varint.
12//! - `bool` — one byte (`0x00` / `0x01`); any other byte is rejected.
13//! - `f32` / `f64` — IEEE 754 bit pattern, little-endian. NaN, ±Inf,
14//!   subnormals, and signed zeros all round-trip bit-for-bit.
15//! - `String` / `&str` — varint length prefix, then UTF-8 bytes.
16//! - `[T; N]` — `N` consecutive `T` encodings, no length prefix (the length
17//!   is in the type).
18//! - `Vec<T>` / `&[T]` — varint length prefix, then `len` consecutive `T`
19//!   encodings.
20//! - tuples (arity 1..=12) — fields concatenated in declaration order.
21//! - `Option<T>` — one tag byte (`0x00` = `None`, `0x01` = `Some`) followed
22//!   by the inner value when present.
23//! - `Result<T, E>` — one tag byte (`0x00` = `Ok`, `0x01` = `Err`) followed
24//!   by the inner value.
25//! - `()` (unit) — zero bytes.
26//! - `BTreeMap` / `BTreeSet` / `HashMap` / `HashSet` — varint count followed
27//!   by the entries sorted lexicographically by their **encoded key bytes**.
28//!   This canonical ordering means a `HashMap` and a `BTreeMap` holding the
29//!   same logical data encode to the same bytes, regardless of insertion
30//!   order or build-flag-dependent hash randomisation.
31//!
32//! [`docs/WIRE_FORMAT.md`]: https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md
33
34use alloc::collections::{BTreeMap, BTreeSet};
35use alloc::string::String;
36use alloc::vec::Vec;
37#[cfg(feature = "std")]
38use std::collections::{HashMap, HashSet};
39#[cfg(feature = "std")]
40use std::hash::{BuildHasher, Hash};
41
42use crate::codec::{Decode, Encode, Encoder};
43use crate::error::{Result, SerialError};
44use crate::traits::{Deserialize, Serialize};
45use crate::varint;
46
47// ---------------------------------------------------------------------------
48// Unsigned integers
49// ---------------------------------------------------------------------------
50
51impl Serialize for u8 {
52    #[inline]
53    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
54        encoder.write_byte(*self)
55    }
56
57    /// Single bulk write — bypasses the per-element loop the default impl
58    /// would emit. For an in-memory [`crate::Encoder`] this compiles to a
59    /// single `Vec::extend_from_slice`; for [`crate::IoEncoder`] it is one
60    /// `Write::write_all`. Either way it replaces N per-byte calls with a
61    /// memcpy.
62    #[inline]
63    fn serialize_slice<E: Encode + ?Sized>(slice: &[u8], encoder: &mut E) -> Result<()> {
64        encoder.write_bytes(slice)
65    }
66}
67
68impl Deserialize for u8 {
69    #[inline]
70    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
71        decoder.read_byte()
72    }
73
74    /// Single bulk read — bypasses the per-element loop the default impl
75    /// would emit. For an in-memory [`crate::Decoder`] this is a bounds
76    /// check plus a memcpy; for [`crate::IoDecoder`] it is one
77    /// `Read::read_exact`. Either way it replaces N per-byte reads with
78    /// one buffer fill.
79    #[inline]
80    fn deserialize_many<D: Decode + ?Sized>(decoder: &mut D, count: usize) -> Result<Vec<u8>> {
81        let mut out = alloc::vec![0u8; count];
82        decoder.read_into(&mut out)?;
83        Ok(out)
84    }
85}
86
87impl Serialize for u16 {
88    #[inline]
89    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
90        encoder.write_varint_u64(u64::from(*self))
91    }
92}
93
94impl Deserialize for u16 {
95    #[inline]
96    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
97        let value = decoder.read_varint_u64()?;
98        u16::try_from(value).map_err(|_| SerialError::IntegerOutOfRange)
99    }
100}
101
102impl Serialize for u32 {
103    #[inline]
104    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
105        encoder.write_varint_u64(u64::from(*self))
106    }
107}
108
109impl Deserialize for u32 {
110    #[inline]
111    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
112        let value = decoder.read_varint_u64()?;
113        u32::try_from(value).map_err(|_| SerialError::IntegerOutOfRange)
114    }
115}
116
117impl Serialize for u64 {
118    #[inline]
119    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
120        encoder.write_varint_u64(*self)
121    }
122}
123
124impl Deserialize for u64 {
125    #[inline]
126    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
127        decoder.read_varint_u64()
128    }
129}
130
131impl Serialize for u128 {
132    #[inline]
133    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
134        encoder.write_varint_u128(*self)
135    }
136}
137
138impl Deserialize for u128 {
139    #[inline]
140    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
141        decoder.read_varint_u128()
142    }
143}
144
145impl Serialize for usize {
146    #[inline]
147    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
148        encoder.write_varint_u64(*self as u64)
149    }
150}
151
152impl Deserialize for usize {
153    #[inline]
154    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
155        let value = decoder.read_varint_u64()?;
156        usize::try_from(value).map_err(|_| SerialError::IntegerOutOfRange)
157    }
158}
159
160// ---------------------------------------------------------------------------
161// Signed integers — ZigZag + varint
162// ---------------------------------------------------------------------------
163
164impl Serialize for i8 {
165    #[inline]
166    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
167        encoder.write_byte(*self as u8)
168    }
169}
170
171impl Deserialize for i8 {
172    #[inline]
173    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
174        Ok(decoder.read_byte()? as i8)
175    }
176}
177
178impl Serialize for i16 {
179    #[inline]
180    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
181        encoder.write_varint_u64(varint::zigzag_encode_i64(i64::from(*self)))
182    }
183}
184
185impl Deserialize for i16 {
186    #[inline]
187    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
188        let value = varint::zigzag_decode_i64(decoder.read_varint_u64()?);
189        i16::try_from(value).map_err(|_| SerialError::IntegerOutOfRange)
190    }
191}
192
193impl Serialize for i32 {
194    #[inline]
195    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
196        encoder.write_varint_u64(varint::zigzag_encode_i64(i64::from(*self)))
197    }
198}
199
200impl Deserialize for i32 {
201    #[inline]
202    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
203        let value = varint::zigzag_decode_i64(decoder.read_varint_u64()?);
204        i32::try_from(value).map_err(|_| SerialError::IntegerOutOfRange)
205    }
206}
207
208impl Serialize for i64 {
209    #[inline]
210    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
211        encoder.write_varint_u64(varint::zigzag_encode_i64(*self))
212    }
213}
214
215impl Deserialize for i64 {
216    #[inline]
217    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
218        Ok(varint::zigzag_decode_i64(decoder.read_varint_u64()?))
219    }
220}
221
222impl Serialize for i128 {
223    #[inline]
224    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
225        encoder.write_varint_u128(varint::zigzag_encode_i128(*self))
226    }
227}
228
229impl Deserialize for i128 {
230    #[inline]
231    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
232        Ok(varint::zigzag_decode_i128(decoder.read_varint_u128()?))
233    }
234}
235
236impl Serialize for isize {
237    #[inline]
238    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
239        encoder.write_varint_u64(varint::zigzag_encode_i64(*self as i64))
240    }
241}
242
243impl Deserialize for isize {
244    #[inline]
245    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
246        let value = varint::zigzag_decode_i64(decoder.read_varint_u64()?);
247        isize::try_from(value).map_err(|_| SerialError::IntegerOutOfRange)
248    }
249}
250
251// ---------------------------------------------------------------------------
252// Bool
253// ---------------------------------------------------------------------------
254
255impl Serialize for bool {
256    #[inline]
257    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
258        encoder.write_byte(u8::from(*self))
259    }
260}
261
262impl Deserialize for bool {
263    #[inline]
264    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
265        match decoder.read_byte()? {
266            0x00 => Ok(false),
267            0x01 => Ok(true),
268            other => Err(SerialError::InvalidBool { byte: other }),
269        }
270    }
271}
272
273// ---------------------------------------------------------------------------
274// Floats — IEEE 754 bit pattern, little-endian
275// ---------------------------------------------------------------------------
276
277impl Serialize for f32 {
278    #[inline]
279    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
280        encoder.write_bytes(&self.to_bits().to_le_bytes())
281    }
282}
283
284impl Deserialize for f32 {
285    #[inline]
286    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
287        let mut buf = [0u8; 4];
288        decoder.read_into(&mut buf)?;
289        Ok(f32::from_bits(u32::from_le_bytes(buf)))
290    }
291}
292
293impl Serialize for f64 {
294    #[inline]
295    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
296        encoder.write_bytes(&self.to_bits().to_le_bytes())
297    }
298}
299
300impl Deserialize for f64 {
301    #[inline]
302    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
303        let mut buf = [0u8; 8];
304        decoder.read_into(&mut buf)?;
305        Ok(f64::from_bits(u64::from_le_bytes(buf)))
306    }
307}
308
309// ---------------------------------------------------------------------------
310// String / &str
311// ---------------------------------------------------------------------------
312
313impl Serialize for str {
314    #[inline]
315    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
316        let bytes = self.as_bytes();
317        encoder.write_varint_u64(bytes.len() as u64)?;
318        encoder.write_bytes(bytes)
319    }
320}
321
322impl Serialize for String {
323    #[inline]
324    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
325        Serialize::serialize(self.as_str(), encoder)
326    }
327}
328
329impl Deserialize for String {
330    #[inline]
331    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
332        let bytes = decoder.read_length_prefixed()?;
333        String::from_utf8(bytes).map_err(|_| SerialError::InvalidUtf8)
334    }
335}
336
337// ---------------------------------------------------------------------------
338// Slices and Vec<T>
339// ---------------------------------------------------------------------------
340
341impl<T: Serialize> Serialize for [T] {
342    #[inline]
343    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
344        encoder.write_varint_u64(self.len() as u64)?;
345        // Dispatch to T's `serialize_slice` so byte-slice payloads
346        // (T = u8) take the memcpy fast path via the `u8` override.
347        T::serialize_slice(self, encoder)
348    }
349}
350
351impl<T: Serialize> Serialize for Vec<T> {
352    #[inline]
353    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
354        Serialize::serialize(self.as_slice(), encoder)
355    }
356}
357
358impl<T: Deserialize> Deserialize for Vec<T> {
359    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
360        let declared = decoder.read_varint_u64()?;
361        let len = guard_element_count::<T, _>(declared, decoder)?;
362        // Dispatch to T's `deserialize_many` so byte-vec payloads
363        // (T = u8) take the memcpy fast path via the `u8` override.
364        T::deserialize_many(decoder, len)
365    }
366}
367
368// ---------------------------------------------------------------------------
369// Fixed-size arrays — [T; N]
370// ---------------------------------------------------------------------------
371
372impl<T: Serialize, const N: usize> Serialize for [T; N] {
373    #[inline]
374    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
375        for item in self {
376            item.serialize(encoder)?;
377        }
378        Ok(())
379    }
380}
381
382impl<T: Deserialize, const N: usize> Deserialize for [T; N] {
383    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
384        let mut out: Vec<T> = Vec::with_capacity(N);
385        for _ in 0..N {
386            out.push(T::deserialize(decoder)?);
387        }
388        out.try_into().map_err(|_| SerialError::IntegerOutOfRange)
389    }
390}
391
392// ---------------------------------------------------------------------------
393// Tuples — arity 0..=12
394// ---------------------------------------------------------------------------
395
396impl Serialize for () {
397    #[inline]
398    fn serialize<E: Encode + ?Sized>(&self, _encoder: &mut E) -> Result<()> {
399        Ok(())
400    }
401}
402
403impl Deserialize for () {
404    #[inline]
405    fn deserialize<D: Decode + ?Sized>(_decoder: &mut D) -> Result<Self> {
406        Ok(())
407    }
408}
409
410macro_rules! impl_tuple {
411    ($($name:ident: $idx:tt),+) => {
412        impl<$($name: Serialize),+> Serialize for ($($name,)+) {
413            #[inline]
414            fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
415                $( self.$idx.serialize(encoder)?; )+
416                Ok(())
417            }
418        }
419
420        impl<$($name: Deserialize),+> Deserialize for ($($name,)+) {
421            #[inline]
422            fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
423                Ok(( $( $name::deserialize(decoder)?, )+ ))
424            }
425        }
426    };
427}
428
429impl_tuple!(T0: 0);
430impl_tuple!(T0: 0, T1: 1);
431impl_tuple!(T0: 0, T1: 1, T2: 2);
432impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3);
433impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4);
434impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5);
435impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6);
436impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7);
437impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8);
438impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9);
439impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9, T10: 10);
440impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9, T10: 10, T11: 11);
441
442// ---------------------------------------------------------------------------
443// Option<T>
444// ---------------------------------------------------------------------------
445
446impl<T: Serialize> Serialize for Option<T> {
447    #[inline]
448    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
449        match self {
450            None => encoder.write_byte(0x00),
451            Some(value) => {
452                encoder.write_byte(0x01)?;
453                value.serialize(encoder)
454            }
455        }
456    }
457}
458
459impl<T: Deserialize> Deserialize for Option<T> {
460    #[inline]
461    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
462        match decoder.read_byte()? {
463            0x00 => Ok(None),
464            0x01 => Ok(Some(T::deserialize(decoder)?)),
465            tag => Err(SerialError::InvalidTag {
466                kind: "Option",
467                tag,
468            }),
469        }
470    }
471}
472
473// ---------------------------------------------------------------------------
474// Result<T, E>
475// ---------------------------------------------------------------------------
476
477impl<T: Serialize, E: Serialize> Serialize for core::result::Result<T, E> {
478    #[inline]
479    fn serialize<Enc: Encode + ?Sized>(&self, encoder: &mut Enc) -> Result<()> {
480        match self {
481            Ok(value) => {
482                encoder.write_byte(0x00)?;
483                value.serialize(encoder)
484            }
485            Err(err) => {
486                encoder.write_byte(0x01)?;
487                err.serialize(encoder)
488            }
489        }
490    }
491}
492
493impl<T: Deserialize, E: Deserialize> Deserialize for core::result::Result<T, E> {
494    #[inline]
495    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
496        match decoder.read_byte()? {
497            0x00 => Ok(Ok(T::deserialize(decoder)?)),
498            0x01 => Ok(Err(E::deserialize(decoder)?)),
499            tag => Err(SerialError::InvalidTag {
500                kind: "Result",
501                tag,
502            }),
503        }
504    }
505}
506
507// ---------------------------------------------------------------------------
508// References — &T forwards to T's Serialize impl
509// ---------------------------------------------------------------------------
510
511impl<T: Serialize + ?Sized> Serialize for &T {
512    #[inline]
513    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
514        (**self).serialize(encoder)
515    }
516}
517
518// ---------------------------------------------------------------------------
519// Map and set collections
520// ---------------------------------------------------------------------------
521//
522// Encoding contract: `varint(count) ++ sorted_entries`, where entries are
523// sorted lexicographically by their **encoded key bytes**. This means a
524// `HashMap` and a `BTreeMap` holding the same logical data encode to the
525// same bytes. Hash-randomisation across runs and insertion order are both
526// irrelevant to the output — the byte-determinism contract holds.
527
528/// Encode `count` entries as `varint(count) ++ each (key, value) pair`,
529/// where entries are pre-sorted by encoded-key bytes.
530///
531/// `count` is a fresh ascending iteration over the source collection. The
532/// helper encodes each `(K, V)` pair to a temporary `Vec<u8>` (capturing the
533/// length of the key portion so the sort step does not re-encode), sorts
534/// those byte representations, then concatenates them onto `encoder`.
535fn encode_map_like<K, V, I, E>(count: usize, entries: I, encoder: &mut E) -> Result<()>
536where
537    K: Serialize,
538    V: Serialize,
539    I: IntoIterator<Item = (K, V)>,
540    E: Encode + ?Sized,
541{
542    let mut buffered: Vec<(usize, Vec<u8>)> = Vec::with_capacity(count);
543    for (k, v) in entries {
544        let mut tmp = Encoder::new();
545        k.serialize(&mut tmp)?;
546        let key_len = tmp.as_bytes().len();
547        v.serialize(&mut tmp)?;
548        buffered.push((key_len, tmp.into_inner()));
549    }
550    buffered.sort_by(|a, b| {
551        let ka = &a.1[..a.0];
552        let kb = &b.1[..b.0];
553        ka.cmp(kb)
554    });
555    encoder.write_varint_u64(count as u64)?;
556    for (_, bytes) in &buffered {
557        encoder.write_bytes(bytes)?;
558    }
559    Ok(())
560}
561
562/// Encode `count` set elements as `varint(count) ++ sorted_elements`.
563fn encode_set_like<T, I, E>(count: usize, items: I, encoder: &mut E) -> Result<()>
564where
565    T: Serialize,
566    I: IntoIterator<Item = T>,
567    E: Encode + ?Sized,
568{
569    let mut buffered: Vec<Vec<u8>> = Vec::with_capacity(count);
570    for item in items {
571        let mut tmp = Encoder::new();
572        item.serialize(&mut tmp)?;
573        buffered.push(tmp.into_inner());
574    }
575    buffered.sort();
576    encoder.write_varint_u64(count as u64)?;
577    for bytes in &buffered {
578        encoder.write_bytes(bytes)?;
579    }
580    Ok(())
581}
582
583impl<K, V> Serialize for BTreeMap<K, V>
584where
585    K: Serialize,
586    V: Serialize,
587{
588    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
589        encode_map_like(self.len(), self.iter(), encoder)
590    }
591}
592
593impl<K, V> Deserialize for BTreeMap<K, V>
594where
595    K: Deserialize + Ord,
596    V: Deserialize,
597{
598    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
599        let declared = decoder.read_varint_u64()?;
600        let len = guard_element_count::<(K, V), _>(declared, decoder)?;
601        let mut out = BTreeMap::new();
602        for _ in 0..len {
603            let k = K::deserialize(decoder)?;
604            let v = V::deserialize(decoder)?;
605            let _ = out.insert(k, v);
606        }
607        Ok(out)
608    }
609}
610
611impl<T> Serialize for BTreeSet<T>
612where
613    T: Serialize,
614{
615    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
616        encode_set_like(self.len(), self.iter(), encoder)
617    }
618}
619
620impl<T> Deserialize for BTreeSet<T>
621where
622    T: Deserialize + Ord,
623{
624    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
625        let declared = decoder.read_varint_u64()?;
626        let len = guard_element_count::<T, _>(declared, decoder)?;
627        let mut out = BTreeSet::new();
628        for _ in 0..len {
629            let _ = out.insert(T::deserialize(decoder)?);
630        }
631        Ok(out)
632    }
633}
634
635#[cfg(feature = "std")]
636impl<K, V, S> Serialize for HashMap<K, V, S>
637where
638    K: Serialize,
639    V: Serialize,
640{
641    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
642        encode_map_like(self.len(), self.iter(), encoder)
643    }
644}
645
646#[cfg(feature = "std")]
647impl<K, V, S> Deserialize for HashMap<K, V, S>
648where
649    K: Deserialize + Hash + Eq,
650    V: Deserialize,
651    S: BuildHasher + Default,
652{
653    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
654        let declared = decoder.read_varint_u64()?;
655        let len = guard_element_count::<(K, V), _>(declared, decoder)?;
656        let mut out = HashMap::with_capacity_and_hasher(initial_capacity(len), S::default());
657        for _ in 0..len {
658            let k = K::deserialize(decoder)?;
659            let v = V::deserialize(decoder)?;
660            let _ = out.insert(k, v);
661        }
662        Ok(out)
663    }
664}
665
666#[cfg(feature = "std")]
667impl<T, S> Serialize for HashSet<T, S>
668where
669    T: Serialize,
670{
671    fn serialize<E: Encode + ?Sized>(&self, encoder: &mut E) -> Result<()> {
672        encode_set_like(self.len(), self.iter(), encoder)
673    }
674}
675
676#[cfg(feature = "std")]
677impl<T, S> Deserialize for HashSet<T, S>
678where
679    T: Deserialize + Hash + Eq,
680    S: BuildHasher + Default,
681{
682    fn deserialize<D: Decode + ?Sized>(decoder: &mut D) -> Result<Self> {
683        let declared = decoder.read_varint_u64()?;
684        let len = guard_element_count::<T, _>(declared, decoder)?;
685        let mut out = HashSet::with_capacity_and_hasher(initial_capacity(len), S::default());
686        for _ in 0..len {
687            let _ = out.insert(T::deserialize(decoder)?);
688        }
689        Ok(out)
690    }
691}
692
693/// Validate `declared` (an element count) against the decoder's
694/// `max_alloc`, treating each element as occupying at least one byte. This
695/// prevents the obvious "declare `u64::MAX` elements, force a giant
696/// `Vec::with_capacity`" attack — declaring more elements than the decoder
697/// could ever supply bytes for is refused before we allocate.
698#[inline]
699fn guard_element_count<T, D: Decode + ?Sized>(declared: u64, decoder: &D) -> Result<usize> {
700    let max = decoder.max_alloc() as u64;
701    if declared > max {
702        return Err(SerialError::InvalidLength {
703            declared,
704            remaining: 0,
705        });
706    }
707    // Type tag silences the unused-type-parameter lint and documents intent.
708    let _phantom: core::marker::PhantomData<T> = core::marker::PhantomData;
709    usize::try_from(declared).map_err(|_| SerialError::IntegerOutOfRange)
710}
711
712/// Cap the **initial** capacity of a collection allocation regardless of
713/// the declared element count.
714///
715/// `guard_element_count` only validates that the declared count fits within
716/// `max_alloc`, but `max_alloc` is denominated in bytes-per-value, while a
717/// `HashMap` slot can occupy 30–50 bytes including hash-table overhead.
718/// A declared count near `max_alloc` would therefore trigger a multi-tens-
719/// of-gigabytes pre-allocation in `with_capacity` — even though the rest of
720/// the decode would fail almost immediately on `UnexpectedEof`.
721///
722/// Capping the initial capacity lets legitimate large collections grow
723/// naturally during the decode loop, while hostile inputs fail fast on the
724/// first missing byte instead of OOMing the host first.
725#[cfg(feature = "std")]
726#[inline]
727fn initial_capacity(declared: usize) -> usize {
728    /// Big enough to avoid most grow-and-copy churn for ordinary-sized
729    /// collections; small enough that an attacker cannot force a multi-GiB
730    /// allocation by sending an inflated count.
731    const INITIAL_CAPACITY_CAP: usize = 4096;
732    declared.min(INITIAL_CAPACITY_CAP)
733}
734
735#[cfg(test)]
736mod tests {
737    use super::*;
738    use crate::{decode, encode};
739    use alloc::vec;
740
741    fn round_trip<T>(value: T)
742    where
743        T: Serialize + Deserialize + PartialEq + core::fmt::Debug,
744    {
745        let bytes = encode(&value).expect("encode");
746        let back: T = decode(&bytes).expect("decode");
747        assert_eq!(back, value);
748    }
749
750    #[test]
751    fn u8_round_trips() {
752        for v in [0u8, 1, 127, 128, 255] {
753            round_trip(v);
754        }
755    }
756
757    #[test]
758    fn u64_round_trips() {
759        for v in [0u64, 1, u32::MAX as u64, u64::MAX] {
760            round_trip(v);
761        }
762    }
763
764    #[test]
765    fn i64_round_trips() {
766        for v in [0i64, -1, 1, i64::MIN, i64::MAX] {
767            round_trip(v);
768        }
769    }
770
771    #[test]
772    fn bool_round_trips() {
773        round_trip(true);
774        round_trip(false);
775    }
776
777    #[test]
778    fn string_round_trips() {
779        for s in ["", "hello", "a longer string with some content"] {
780            round_trip(String::from(s));
781        }
782    }
783
784    #[test]
785    fn vec_u8_round_trips() {
786        round_trip::<Vec<u8>>(vec![]);
787        round_trip::<Vec<u8>>(vec![0u8, 1, 2, 3]);
788        round_trip::<Vec<u8>>(vec![0xffu8; 1024]);
789    }
790
791    #[test]
792    fn vec_u32_round_trips() {
793        round_trip::<Vec<u32>>(vec![]);
794        round_trip::<Vec<u32>>(vec![1, 2, u32::MAX]);
795    }
796
797    #[test]
798    fn vec_string_round_trips() {
799        round_trip(vec![
800            String::from("hello"),
801            String::from("world"),
802            String::new(),
803        ]);
804    }
805
806    #[test]
807    fn array_round_trips() {
808        round_trip([1u32, 2, 3, 4]);
809        round_trip([0u8; 0]);
810    }
811
812    #[test]
813    fn tuple_round_trips() {
814        round_trip((1u8, 2u16, 3u32));
815        round_trip((String::from("a"), 42u64, -3i32));
816    }
817
818    #[test]
819    fn option_round_trips() {
820        round_trip::<Option<u64>>(None);
821        round_trip::<Option<u64>>(Some(42));
822        round_trip::<Option<String>>(Some(String::from("hi")));
823    }
824
825    #[test]
826    fn result_round_trips() {
827        round_trip::<core::result::Result<u64, String>>(Ok(7));
828        round_trip::<core::result::Result<u64, String>>(Err(String::from("nope")));
829    }
830
831    #[test]
832    fn invalid_bool_byte_is_rejected() {
833        let err = decode::<bool>(&[0x7f]).expect_err("0x7f is not a bool");
834        assert!(matches!(err, SerialError::InvalidBool { byte: 0x7f }));
835    }
836
837    #[test]
838    fn string_with_invalid_utf8_is_rejected() {
839        let bytes = [0x02, 0xff, 0xff];
840        let err = decode::<String>(&bytes).expect_err("invalid UTF-8 should fail");
841        assert!(matches!(err, SerialError::InvalidUtf8));
842    }
843
844    #[test]
845    fn option_invalid_tag_is_rejected() {
846        let err = decode::<Option<u8>>(&[0x02]).expect_err("0x02 is not a valid Option tag");
847        assert!(matches!(
848            err,
849            SerialError::InvalidTag {
850                kind: "Option",
851                tag: 0x02
852            }
853        ));
854    }
855
856    #[test]
857    fn result_invalid_tag_is_rejected() {
858        let err =
859            decode::<core::result::Result<u8, u8>>(&[0x02]).expect_err("0x02 is not a Result tag");
860        assert!(matches!(
861            err,
862            SerialError::InvalidTag {
863                kind: "Result",
864                tag: 0x02
865            }
866        ));
867    }
868
869    #[test]
870    fn f64_round_trips_including_inf() {
871        for v in [
872            0.0f64,
873            -0.0,
874            1.0,
875            -1.0,
876            f64::MIN,
877            f64::MAX,
878            f64::INFINITY,
879            f64::NEG_INFINITY,
880        ] {
881            let bytes = encode(&v).unwrap();
882            let back: f64 = decode(&bytes).unwrap();
883            assert_eq!(back.to_bits(), v.to_bits());
884        }
885    }
886
887    #[test]
888    fn f64_nan_round_trips_bit_for_bit() {
889        let v = f64::NAN;
890        let bytes = encode(&v).unwrap();
891        let back: f64 = decode(&bytes).unwrap();
892        assert_eq!(back.to_bits(), v.to_bits());
893        assert!(back.is_nan());
894    }
895
896    #[test]
897    fn btreemap_round_trips() {
898        let mut m = BTreeMap::new();
899        let _ = m.insert(String::from("a"), 1u32);
900        let _ = m.insert(String::from("b"), 2);
901        let _ = m.insert(String::from("c"), 3);
902        round_trip(m);
903    }
904
905    #[test]
906    fn btreemap_empty_round_trips() {
907        round_trip(BTreeMap::<u32, u32>::new());
908    }
909
910    #[test]
911    fn btreeset_round_trips() {
912        let mut s = BTreeSet::new();
913        let _ = s.insert(1u32);
914        let _ = s.insert(2);
915        let _ = s.insert(3);
916        round_trip(s);
917    }
918
919    #[cfg(feature = "std")]
920    #[test]
921    fn hashmap_round_trips() {
922        let mut m: HashMap<String, u32> = HashMap::new();
923        let _ = m.insert(String::from("alpha"), 1);
924        let _ = m.insert(String::from("beta"), 2);
925        round_trip(m);
926    }
927
928    #[cfg(feature = "std")]
929    #[test]
930    fn hashset_round_trips() {
931        let mut s: HashSet<u32> = HashSet::new();
932        let _ = s.insert(1);
933        let _ = s.insert(7);
934        let _ = s.insert(42);
935        round_trip(s);
936    }
937
938    #[cfg(feature = "std")]
939    #[test]
940    fn hashmap_and_btreemap_encode_identically_for_same_data() {
941        let mut h: HashMap<String, u32> = HashMap::new();
942        let mut b: BTreeMap<String, u32> = BTreeMap::new();
943        for (k, v) in [("zeta", 5u32), ("alpha", 1), ("delta", 4), ("beta", 2)] {
944            let _ = h.insert(k.into(), v);
945            let _ = b.insert(k.into(), v);
946        }
947        assert_eq!(encode(&h).unwrap(), encode(&b).unwrap());
948    }
949
950    #[cfg(feature = "std")]
951    #[test]
952    fn hashmap_insertion_order_independent() {
953        let mut a: HashMap<u32, u32> = HashMap::new();
954        let _ = a.insert(1, 10);
955        let _ = a.insert(2, 20);
956        let _ = a.insert(3, 30);
957
958        let mut b: HashMap<u32, u32> = HashMap::new();
959        let _ = b.insert(3, 30);
960        let _ = b.insert(1, 10);
961        let _ = b.insert(2, 20);
962
963        assert_eq!(encode(&a).unwrap(), encode(&b).unwrap());
964    }
965
966    #[test]
967    fn collection_with_hostile_element_count_is_rejected() {
968        // varint(u64::MAX) is 10 bytes of 0xff... 0x01.
969        let bytes: [u8; 10] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01];
970        let err = decode::<Vec<u32>>(&bytes).expect_err("hostile count");
971        assert!(matches!(err, SerialError::InvalidLength { .. }));
972    }
973}