nanoserde/
serde_bin.rs

1use core::convert::TryInto;
2use core::error::Error;
3
4use alloc::borrow::ToOwned;
5use alloc::boxed::Box;
6use alloc::collections::{BTreeMap, BTreeSet, LinkedList};
7use alloc::string::String;
8use alloc::vec::Vec;
9
10/// A trait for objects that can be serialized to binary.
11pub trait SerBin {
12    /// Serialize Self to bytes.
13    ///
14    /// This is a convenient wrapper around `ser_bin`.
15    fn serialize_bin(&self) -> Vec<u8> {
16        let mut s = Vec::new();
17        self.ser_bin(&mut s);
18        s
19    }
20
21    /// Serialize Self to bytes.
22    ///
23    /// ```rust
24    /// # use nanoserde::*;
25    /// let mut s = Vec::new();
26    /// 42u32.ser_bin(&mut s);
27    /// assert_eq!(s, vec![42, 0, 0, 0])
28    /// ```
29    fn ser_bin(&self, output: &mut Vec<u8>);
30}
31
32/// A trait for objects that can be deserialized from binary.
33pub trait DeBin: Sized {
34    /// Parse Self from the input bytes.
35    ///
36    /// This is a convenient wrapper around `de_bin`.
37    fn deserialize_bin(d: &[u8]) -> Result<Self, DeBinErr> {
38        DeBin::de_bin(&mut 0, d)
39    }
40
41    /// Parse Self from the input bytes starting at index `offset`.
42    ///
43    /// After deserialization, `offset` is updated to point at the byte after
44    /// the last one used.
45    ///
46    /// ```rust
47    /// # use nanoserde::*;
48    /// let bytes = [1, 0, 0, 0, 2, 0, 0, 0];
49    /// let mut offset = 4;
50    /// let two = u32::de_bin(&mut offset, &bytes).unwrap();
51    /// assert_eq!(two, 2);
52    /// assert_eq!(offset, 8);
53    /// ```
54    fn de_bin(offset: &mut usize, bytes: &[u8]) -> Result<Self, DeBinErr>;
55}
56
57#[derive(Clone)]
58#[non_exhaustive]
59pub enum DeBinErrReason {
60    Length {
61        /// Expected Length
62        expected_length: usize,
63        /// Actual Length
64        actual_length: usize,
65    },
66}
67
68/// The error message when failing to deserialize.
69#[derive(Clone)]
70pub struct DeBinErr {
71    /// Offset
72    pub o: usize,
73    pub msg: DeBinErrReason,
74}
75
76impl DeBinErr {
77    /// Helper for constructing [`DeBinErr`]
78    pub fn new(offset: usize, expected_length: usize, actual_length: usize) -> Self {
79        Self {
80            o: offset,
81            msg: DeBinErrReason::Length {
82                expected_length,
83                actual_length,
84            },
85        }
86    }
87}
88
89impl core::fmt::Debug for DeBinErr {
90    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91        match self.msg {
92            DeBinErrReason::Length {
93                expected_length: l,
94                actual_length: s,
95            } => write!(
96                f,
97                "Bin deserialize error at:{} wanted:{} bytes but max size is {}",
98                self.o, l, s
99            ),
100        }
101    }
102}
103
104impl core::fmt::Display for DeBinErr {
105    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106        core::fmt::Debug::fmt(self, f)
107    }
108}
109
110impl Error for DeBinErr {}
111
112macro_rules! impl_ser_de_bin_for {
113    ($ty:ident) => {
114        impl SerBin for $ty {
115            fn ser_bin(&self, s: &mut Vec<u8>) {
116                let du8 = self.to_le_bytes();
117                s.extend_from_slice(&du8);
118            }
119        }
120
121        impl DeBin for $ty {
122            fn de_bin(o: &mut usize, d: &[u8]) -> Result<$ty, DeBinErr> {
123                let expected_length = core::mem::size_of::<$ty>();
124                if *o + expected_length > d.len() {
125                    return Err(DeBinErr {
126                        o: *o,
127                        msg: DeBinErrReason::Length {
128                            expected_length,
129                            actual_length: d.len(),
130                        },
131                    });
132                }
133
134                // We just checked that the correct amount of bytes are available,
135                // and there are no invalid bit patterns for these primitives. This
136                // unwrap should be impossible to hit.
137                let ret: $ty =
138                    <$ty>::from_le_bytes(d[*o..(*o + expected_length)].try_into().unwrap());
139                *o += expected_length;
140                Ok(ret)
141            }
142        }
143    };
144}
145
146impl_ser_de_bin_for!(f64);
147impl_ser_de_bin_for!(f32);
148impl_ser_de_bin_for!(u128);
149impl_ser_de_bin_for!(i128);
150impl_ser_de_bin_for!(u64);
151impl_ser_de_bin_for!(i64);
152impl_ser_de_bin_for!(u32);
153impl_ser_de_bin_for!(i32);
154impl_ser_de_bin_for!(u16);
155impl_ser_de_bin_for!(i16);
156impl_ser_de_bin_for!(i8);
157
158impl SerBin for usize {
159    fn ser_bin(&self, s: &mut Vec<u8>) {
160        let u64usize = *self as u64;
161        let du8 = u64usize.to_le_bytes();
162        s.extend_from_slice(&du8);
163    }
164}
165
166impl DeBin for usize {
167    fn de_bin(o: &mut usize, d: &[u8]) -> Result<usize, DeBinErr> {
168        let l = core::mem::size_of::<u64>();
169
170        let m = match d.get(*o..*o + l) {
171            Some(data) => u64::from_le_bytes(data.try_into().unwrap()),
172            None => {
173                return Err(DeBinErr {
174                    o: *o,
175                    msg: DeBinErrReason::Length {
176                        expected_length: l,
177                        actual_length: d.len(),
178                    },
179                });
180            }
181        };
182
183        *o += l;
184        Ok(m as usize)
185    }
186}
187
188impl DeBin for u8 {
189    fn de_bin(o: &mut usize, d: &[u8]) -> Result<u8, DeBinErr> {
190        if *o + 1 > d.len() {
191            return Err(DeBinErr {
192                o: *o,
193                msg: DeBinErrReason::Length {
194                    expected_length: 1,
195                    actual_length: d.len(),
196                },
197            });
198        }
199        let m = d[*o];
200        *o += 1;
201        Ok(m)
202    }
203}
204
205impl SerBin for u8 {
206    fn ser_bin(&self, s: &mut Vec<u8>) {
207        s.push(*self);
208    }
209}
210
211impl SerBin for bool {
212    fn ser_bin(&self, s: &mut Vec<u8>) {
213        s.push(if *self { 1 } else { 0 });
214    }
215}
216
217impl DeBin for bool {
218    fn de_bin(o: &mut usize, d: &[u8]) -> Result<bool, DeBinErr> {
219        if *o + 1 > d.len() {
220            return Err(DeBinErr {
221                o: *o,
222                msg: DeBinErrReason::Length {
223                    expected_length: 1,
224                    actual_length: d.len(),
225                },
226            });
227        }
228        let m = d[*o];
229        *o += 1;
230        if m == 0 {
231            Ok(false)
232        } else {
233            Ok(true)
234        }
235    }
236}
237
238impl SerBin for String {
239    fn ser_bin(&self, s: &mut Vec<u8>) {
240        let len = self.len();
241        len.ser_bin(s);
242        s.extend_from_slice(self.as_bytes());
243    }
244}
245
246impl DeBin for String {
247    fn de_bin(o: &mut usize, d: &[u8]) -> Result<String, DeBinErr> {
248        let len: usize = DeBin::de_bin(o, d)?;
249        if *o + len > d.len() {
250            return Err(DeBinErr {
251                o: *o,
252                msg: DeBinErrReason::Length {
253                    expected_length: 1,
254                    actual_length: d.len(),
255                },
256            });
257        }
258        let r = match core::str::from_utf8(&d[*o..(*o + len)]) {
259            Ok(r) => r.to_owned(),
260            Err(_) => {
261                return Err(DeBinErr {
262                    o: *o,
263                    msg: DeBinErrReason::Length {
264                        expected_length: len,
265                        actual_length: d.len(),
266                    },
267                })
268            }
269        };
270        *o += len;
271        Ok(r)
272    }
273}
274
275impl<T> SerBin for Vec<T>
276where
277    T: SerBin,
278{
279    fn ser_bin(&self, s: &mut Vec<u8>) {
280        let len = self.len();
281        len.ser_bin(s);
282        for item in self {
283            item.ser_bin(s);
284        }
285    }
286}
287
288impl<T> DeBin for Vec<T>
289where
290    T: DeBin,
291{
292    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Vec<T>, DeBinErr> {
293        let len: usize = DeBin::de_bin(o, d)?;
294        let mut out = Vec::with_capacity(len);
295        for _ in 0..len {
296            out.push(DeBin::de_bin(o, d)?)
297        }
298        Ok(out)
299    }
300}
301
302impl<T> SerBin for LinkedList<T>
303where
304    T: SerBin,
305{
306    fn ser_bin(&self, s: &mut Vec<u8>) {
307        let len = self.len();
308        len.ser_bin(s);
309        for item in self.iter() {
310            item.ser_bin(s);
311        }
312    }
313}
314
315impl<T> DeBin for LinkedList<T>
316where
317    T: DeBin,
318{
319    fn de_bin(o: &mut usize, d: &[u8]) -> Result<LinkedList<T>, DeBinErr> {
320        let len: usize = DeBin::de_bin(o, d)?;
321        let mut out = LinkedList::new();
322        for _ in 0..len {
323            out.push_back(DeBin::de_bin(o, d)?)
324        }
325        Ok(out)
326    }
327}
328
329#[cfg(feature = "std")]
330impl<T> SerBin for std::collections::HashSet<T>
331where
332    T: SerBin,
333{
334    fn ser_bin(&self, s: &mut Vec<u8>) {
335        let len = self.len();
336        len.ser_bin(s);
337        for item in self.iter() {
338            item.ser_bin(s);
339        }
340    }
341}
342
343#[cfg(feature = "std")]
344impl<T> DeBin for std::collections::HashSet<T>
345where
346    T: DeBin + core::hash::Hash + Eq,
347{
348    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Self, DeBinErr> {
349        let len: usize = DeBin::de_bin(o, d)?;
350        let mut out = std::collections::HashSet::with_capacity(len);
351        for _ in 0..len {
352            out.insert(DeBin::de_bin(o, d)?);
353        }
354        Ok(out)
355    }
356}
357
358impl<T> SerBin for BTreeSet<T>
359where
360    T: SerBin,
361{
362    fn ser_bin(&self, s: &mut Vec<u8>) {
363        let len = self.len();
364        len.ser_bin(s);
365        for item in self.iter() {
366            item.ser_bin(s);
367        }
368    }
369}
370
371impl<T> DeBin for BTreeSet<T>
372where
373    T: DeBin + Ord,
374{
375    fn de_bin(o: &mut usize, d: &[u8]) -> Result<BTreeSet<T>, DeBinErr> {
376        let len: usize = DeBin::de_bin(o, d)?;
377        let mut out = BTreeSet::new();
378        for _ in 0..len {
379            out.insert(DeBin::de_bin(o, d)?);
380        }
381        Ok(out)
382    }
383}
384
385impl<T> SerBin for Option<T>
386where
387    T: SerBin,
388{
389    fn ser_bin(&self, s: &mut Vec<u8>) {
390        if let Some(v) = self {
391            s.push(1);
392            v.ser_bin(s);
393        } else {
394            s.push(0);
395        }
396    }
397}
398
399impl<T> DeBin for Option<T>
400where
401    T: DeBin,
402{
403    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Option<T>, DeBinErr> {
404        if *o + 1 > d.len() {
405            return Err(DeBinErr {
406                o: *o,
407                msg: DeBinErrReason::Length {
408                    expected_length: 1,
409                    actual_length: d.len(),
410                },
411            });
412        }
413        let m = d[*o];
414        *o += 1;
415        if m == 1 {
416            Ok(Some(DeBin::de_bin(o, d)?))
417        } else {
418            Ok(None)
419        }
420    }
421}
422
423impl<T> SerBin for [T]
424where
425    T: SerBin,
426{
427    fn ser_bin(&self, s: &mut Vec<u8>) {
428        for item in self {
429            item.ser_bin(s);
430        }
431    }
432}
433
434impl<T, const N: usize> SerBin for [T; N]
435where
436    T: SerBin,
437{
438    #[inline(always)]
439    fn ser_bin(&self, s: &mut Vec<u8>) {
440        self.as_slice().ser_bin(s)
441    }
442}
443
444impl<T, const N: usize> DeBin for [T; N]
445where
446    T: DeBin,
447{
448    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Self, DeBinErr> {
449        use core::mem::MaybeUninit;
450
451        // waiting for uninit_array(or for array::try_from_fn) stabilization
452        // https://github.com/rust-lang/rust/issues/96097
453        // https://github.com/rust-lang/rust/issues/89379
454        let mut to: [MaybeUninit<T>; N] =
455            unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
456
457        for index in 0..N {
458            to[index] = match DeBin::de_bin(o, d) {
459                Ok(v) => MaybeUninit::new(v),
460                Err(e) => {
461                    // drop all the MaybeUninit values which we've already
462                    // successfully deserialized so we don't leak memory.
463                    // See https://github.com/not-fl3/nanoserde/issues/79
464                    for (_, to_drop) in (0..index).zip(to) {
465                        unsafe { to_drop.assume_init() };
466                    }
467                    return Err(e);
468                }
469            }
470        }
471
472        // waiting for array_assume_init or core::array::map optimizations
473        // https://github.com/rust-lang/rust/issues/61956
474        Ok(unsafe { (*(&to as *const _ as *const MaybeUninit<_>)).assume_init_read() })
475    }
476}
477
478impl SerBin for () {
479    #[inline(always)]
480    fn ser_bin(&self, _s: &mut Vec<u8>) {
481        // do nothing
482    }
483}
484
485impl DeBin for () {
486    #[inline(always)]
487    fn de_bin(_o: &mut usize, _d: &[u8]) -> Result<Self, DeBinErr> {
488        Ok(())
489    }
490}
491
492impl<A, B> SerBin for (A, B)
493where
494    A: SerBin,
495    B: SerBin,
496{
497    fn ser_bin(&self, s: &mut Vec<u8>) {
498        self.0.ser_bin(s);
499        self.1.ser_bin(s);
500    }
501}
502
503impl<A, B> DeBin for (A, B)
504where
505    A: DeBin,
506    B: DeBin,
507{
508    fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B), DeBinErr> {
509        Ok((DeBin::de_bin(o, d)?, DeBin::de_bin(o, d)?))
510    }
511}
512
513impl<A, B, C> SerBin for (A, B, C)
514where
515    A: SerBin,
516    B: SerBin,
517    C: SerBin,
518{
519    fn ser_bin(&self, s: &mut Vec<u8>) {
520        self.0.ser_bin(s);
521        self.1.ser_bin(s);
522        self.2.ser_bin(s);
523    }
524}
525
526impl<A, B, C> DeBin for (A, B, C)
527where
528    A: DeBin,
529    B: DeBin,
530    C: DeBin,
531{
532    fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B, C), DeBinErr> {
533        Ok((
534            DeBin::de_bin(o, d)?,
535            DeBin::de_bin(o, d)?,
536            DeBin::de_bin(o, d)?,
537        ))
538    }
539}
540
541impl<A, B, C, D> SerBin for (A, B, C, D)
542where
543    A: SerBin,
544    B: SerBin,
545    C: SerBin,
546    D: SerBin,
547{
548    fn ser_bin(&self, s: &mut Vec<u8>) {
549        self.0.ser_bin(s);
550        self.1.ser_bin(s);
551        self.2.ser_bin(s);
552        self.3.ser_bin(s);
553    }
554}
555
556impl<A, B, C, D> DeBin for (A, B, C, D)
557where
558    A: DeBin,
559    B: DeBin,
560    C: DeBin,
561    D: DeBin,
562{
563    fn de_bin(o: &mut usize, d: &[u8]) -> Result<(A, B, C, D), DeBinErr> {
564        Ok((
565            DeBin::de_bin(o, d)?,
566            DeBin::de_bin(o, d)?,
567            DeBin::de_bin(o, d)?,
568            DeBin::de_bin(o, d)?,
569        ))
570    }
571}
572
573#[cfg(feature = "std")]
574impl<K, V> SerBin for std::collections::HashMap<K, V>
575where
576    K: SerBin,
577    V: SerBin,
578{
579    fn ser_bin(&self, s: &mut Vec<u8>) {
580        let len = self.len();
581        len.ser_bin(s);
582        for (k, v) in self {
583            k.ser_bin(s);
584            v.ser_bin(s);
585        }
586    }
587}
588
589#[cfg(feature = "std")]
590impl<K, V> DeBin for std::collections::HashMap<K, V>
591where
592    K: DeBin + core::cmp::Eq + core::hash::Hash,
593    V: DeBin,
594{
595    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Self, DeBinErr> {
596        let len: usize = DeBin::de_bin(o, d)?;
597        let mut h = std::collections::HashMap::with_capacity(len);
598        for _ in 0..len {
599            let k = DeBin::de_bin(o, d)?;
600            let v = DeBin::de_bin(o, d)?;
601            h.insert(k, v);
602        }
603        Ok(h)
604    }
605}
606
607impl<K, V> SerBin for BTreeMap<K, V>
608where
609    K: SerBin,
610    V: SerBin,
611{
612    fn ser_bin(&self, s: &mut Vec<u8>) {
613        let len = self.len();
614        len.ser_bin(s);
615        for (k, v) in self {
616            k.ser_bin(s);
617            v.ser_bin(s);
618        }
619    }
620}
621
622impl<K, V> DeBin for BTreeMap<K, V>
623where
624    K: DeBin + core::cmp::Eq + Ord,
625    V: DeBin,
626{
627    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Self, DeBinErr> {
628        let len: usize = DeBin::de_bin(o, d)?;
629        let mut h = BTreeMap::new();
630        for _ in 0..len {
631            let k = DeBin::de_bin(o, d)?;
632            let v = DeBin::de_bin(o, d)?;
633            h.insert(k, v);
634        }
635        Ok(h)
636    }
637}
638
639impl<T> SerBin for Box<T>
640where
641    T: SerBin,
642{
643    fn ser_bin(&self, s: &mut Vec<u8>) {
644        (**self).ser_bin(s)
645    }
646}
647
648impl<T> DeBin for Box<T>
649where
650    T: DeBin,
651{
652    fn de_bin(o: &mut usize, d: &[u8]) -> Result<Box<T>, DeBinErr> {
653        Ok(Box::new(DeBin::de_bin(o, d)?))
654    }
655}