Skip to main content

buffertk/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::fmt::Debug;
4
5mod varint;
6
7pub use varint::v64;
8
9/////////////////////////////////////////////// Error //////////////////////////////////////////////
10
11/// All Error conditions within `buffertk`.
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub enum Error {
14    /// BufferTooShort indicates that there was a need to pack or unpack more bytes than were
15    /// available in the underlying memory.
16    BufferTooShort {
17        /// Number of bytes required to read the buffer.
18        required: usize,
19        /// Number of bytes available to read.
20        had: usize,
21    },
22    /// VarintOverflow indicates that a varint field did not terminate with a number < 128.
23    VarintOverflow {
24        /// Number of bytes in the varint.
25        bytes: usize,
26    },
27    /// UnsignedOverflow indicates that a value will not fit its intended (unsigned) target.
28    UnsignedOverflow {
29        /// Value that would overflow (typically a u32).
30        value: u64,
31    },
32    /// SignedOverflow indicates that a value will not fit its intended (signed) target.
33    SignedOverflow {
34        /// Value that would overflow (typically an i32).
35        value: i64,
36    },
37    /// TagTooLarge indicates the tag would overflow a 32-bit number.
38    TagTooLarge {
39        /// Value that's too large for a tag.
40        tag: u64,
41    },
42    /// UnknownDiscriminant indicates a variant that is not understood by this code.
43    UnknownDiscriminant {
44        /// Discriminant that's not known.
45        discriminant: u32,
46    },
47    /// NotAChar indicates that the prescribed value was tried to unpack as a char, but it's not a
48    /// char.
49    NotAChar {
50        /// Value that's not a char.
51        value: u32,
52    },
53}
54
55impl std::fmt::Display for Error {
56    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        match self {
58            Error::BufferTooShort { required, had } => fmt
59                .debug_struct("BufferTooShort")
60                .field("required", required)
61                .field("had", had)
62                .finish(),
63            Error::VarintOverflow { bytes } => fmt
64                .debug_struct("VarintOverflow")
65                .field("bytes", bytes)
66                .finish(),
67            Error::UnsignedOverflow { value } => fmt
68                .debug_struct("UnsignedOverflow")
69                .field("value", value)
70                .finish(),
71            Error::SignedOverflow { value } => fmt
72                .debug_struct("SignedOverflow")
73                .field("value", value)
74                .finish(),
75            Error::TagTooLarge { tag } => {
76                fmt.debug_struct("TagTooLarge").field("tag", tag).finish()
77            }
78            Error::UnknownDiscriminant { discriminant } => fmt
79                .debug_struct("UnknownDiscriminant")
80                .field("discriminant", discriminant)
81                .finish(),
82            Error::NotAChar { value } => {
83                fmt.debug_struct("NotAChar").field("value", value).finish()
84            }
85        }
86    }
87}
88
89///////////////////////////////////////////// Packable /////////////////////////////////////////////
90
91/// Packable objects can be serialized into an `&mut [u8]`.
92///
93/// The actual serialized form of the object is left unspecified by the Packable trait.  
94///
95/// Packable objects should avoid interior mutability to the extent necessary to ensure that anyone
96/// holding a immutable reference can assume the packed output will not change for the duration of
97/// the reference.
98pub trait Packable {
99    /// `pack_sz` returns the number of bytes required to serialize the Packable object.
100    fn pack_sz(&self) -> usize;
101    /// `pack` fills in the buffer `out` with the packed binary representation of the Packable
102    /// object.  The implementor is responsible to ensure that `out` is exactly `pack_sz()` bytes
103    /// and implementations are encouraged to assert this.
104    ///
105    /// The call to pack should never fail.  Good Rust practices dictate that objects should use
106    /// the type system to enforce their well-formed-ness.  Consequently, we will assume here that
107    /// any well-formed Packable that can be represented will serialize successfully.  If there is
108    /// a need to represent a state that cannot exist, it should be done using a different type
109    /// that does not implement Packable.
110    ///
111    /// # Panics
112    ///
113    /// - When `out.len() != self.pack_sz()`
114    fn pack(&self, out: &mut [u8]);
115    /// `stream` writes the object to the provided writer using the same representation that would
116    /// be used in a call to `pack`.  The implementor is responsible for making sure that the
117    /// number of bytes written is exactly equal to the number of required bytes.
118    ///
119    /// A default implementation is provided that will pack a vector and then write said vector to
120    /// the file with `write_all`.
121    fn stream<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, std::io::Error>
122    where
123        Self: std::marker::Sized,
124        for<'a> &'a Self: Packable,
125    {
126        let pa = stack_pack(self);
127        let vec: Vec<u8> = pa.to_vec();
128        match writer.write_all(&vec) {
129            Ok(_) => Ok(vec.len()),
130            Err(x) => Err(x),
131        }
132    }
133}
134
135//////////////////////////////////////////// Unpackable ////////////////////////////////////////////
136
137/// Unpackable objects can be deserialized from an `&[u8]`.
138///
139/// The format understood by `T:Unpackable` must correspond to the format serialized by
140/// `T:Packable`.
141pub trait Unpackable<'a>: Sized {
142    /// Type of error this unpackable returns.
143    type Error: Debug;
144
145    /// `unpack` attempts to return an Unpackable object stored in a prefix of `buf`.  The method
146    /// returns the result and remaining unused buffer.
147    fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Self::Error>;
148}
149
150//////////////////////////////////////////// pack_helper ///////////////////////////////////////////
151
152/// `pack_helper` takes a Packable object and an `&mut [u8]` and does the work to serialize the
153/// packable into a prefix of the buffer.  The return value is the portion of the buffer that
154/// remains unfilled after this operation.
155pub fn pack_helper<T: Packable>(t: T, buf: &mut [u8]) -> &mut [u8] {
156    let sz: usize = t.pack_sz();
157    assert!(sz <= buf.len(), "packers should never be given short space");
158    t.pack(&mut buf[..sz]);
159    &mut buf[sz..]
160}
161
162//////////////////////////////////////////// StackPacker ///////////////////////////////////////////
163
164const EMPTY: () = ();
165
166/// `stack_pack` begins a tree of packable data on the stack.
167pub fn stack_pack<'a, T: Packable + 'a>(t: T) -> StackPacker<'a, (), T> {
168    StackPacker { prefix: &EMPTY, t }
169}
170
171/// [StackPacker] is the type returned by StackPack.  It's a pointer to something packable (usually
172/// another StackPacker) and some type that we can directly pack.  Both are packable, but it's
173/// usually the case that the former is another StackPacker while the latter is the type being
174/// serialized in a call to `pack`.
175pub struct StackPacker<'a, P, T>
176where
177    P: Packable + 'a,
178    T: Packable + 'a,
179{
180    prefix: &'a P,
181    t: T,
182}
183
184impl<'a, P, T> StackPacker<'a, P, T>
185where
186    P: Packable + 'a,
187    T: Packable + 'a,
188{
189    /// `pack` returns a new StackPacker that will pack `self` at its prefix.  This does not
190    /// actually do the packing, but defers it until calls to e.g. `into_slice`.  Consequently, the
191    /// object `u` must not change between this call and subsequent calls.  Rust's type system
192    /// generally enforces this by default, except where interior mutability is specifically added.
193    pub fn pack<'b, U: Packable + 'b>(&'b self, u: U) -> StackPacker<'b, Self, U> {
194        StackPacker { prefix: self, t: u }
195    }
196
197    /// `into_slice` packs the entire chain of `pack()` calls into the provided mutable buffer.
198    /// The return value is a slice containing exactly those bytes written and no more.
199    pub fn into_slice<'b>(&self, buf: &'b mut [u8]) -> &'b mut [u8] {
200        let len = self.pack_sz();
201        assert!(buf.len() >= len);
202        let buf = &mut buf[0..len];
203        Packable::pack(self, buf);
204        buf
205    }
206
207    /// `to_vec` allocates a new vector and packs the entire chain of `pack()` calls into it.  The
208    /// return value is a `Vec<u8>` sized to exactly the packed bytes.
209    pub fn to_vec(&self) -> Vec<u8> {
210        let len = self.pack_sz();
211        let mut buf = vec![0u8; len];
212        Packable::pack(self, &mut buf);
213        buf
214    }
215
216    /// `append_to_vec` is a helper to extend a vector by the requisite size and then pack into the
217    /// newly created space.
218    pub fn append_to_vec(&self, v: &mut Vec<u8>) {
219        let len = self.pack_sz();
220        let v_sz = v.len();
221        v.resize(v_sz + len, 0);
222        Packable::pack(self, &mut v[v_sz..]);
223    }
224
225    /// Create a Packable object that will pack like `"<varint-length><bytes>"` where the length
226    /// indicates how many bytes there are.  Nothing gets copied.  Usually this gets passed to
227    /// another `stack_pack`, which will do the work.
228    pub fn length_prefixed(&'a self) -> LengthPrefixer<'a, StackPacker<'a, P, T>> {
229        LengthPrefixer {
230            size: self.pack_sz(),
231            body: self,
232        }
233    }
234}
235
236impl<'a, P, T> Packable for StackPacker<'a, P, T>
237where
238    P: Packable + 'a,
239    T: Packable + 'a,
240{
241    fn pack_sz(&self) -> usize {
242        self.prefix.pack_sz() + self.t.pack_sz()
243    }
244
245    fn pack(&self, out: &mut [u8]) {
246        let (prefix, suffix): (&mut [u8], &mut [u8]) = out.split_at_mut(self.prefix.pack_sz());
247        self.prefix.pack(prefix);
248        self.t.pack(suffix);
249    }
250}
251
252///////////////////////////////////////////// Unpacker /////////////////////////////////////////////
253
254/// Unpacker parses a buffer start to finish.
255#[derive(Clone, Default)]
256pub struct Unpacker<'a> {
257    buf: &'a [u8],
258}
259
260impl<'a> Unpacker<'a> {
261    /// Create a new [Unpacker] that parses `buf`.
262    pub fn new(buf: &'a [u8]) -> Self {
263        Self { buf }
264    }
265
266    /// Unpack from buf into an object of type T.
267    pub fn unpack<'b, E, T: Unpackable<'b, Error = E>>(&mut self) -> Result<T, E>
268    where
269        'a: 'b,
270    {
271        let (t, buf): (T, &'a [u8]) = Unpackable::unpack(self.buf)?;
272        self.buf = buf;
273        Ok(t)
274    }
275
276    /// Return true if and only if there's no buffer left to parse.
277    pub fn is_empty(&self) -> bool {
278        self.buf.is_empty()
279    }
280
281    /// Return the remaining buffer.
282    pub fn remain(&self) -> &'a [u8] {
283        self.buf
284    }
285
286    /// Advance the buffer by `by`.  Saturating.
287    pub fn advance(&mut self, by: usize) {
288        if by > self.buf.len() {
289            self.buf = &[];
290        } else {
291            self.buf = &self.buf[by..];
292        }
293    }
294}
295
296////////////////////////////////////////// Packable for &P /////////////////////////////////////////
297
298impl<P: Packable> Packable for &P {
299    fn pack_sz(&self) -> usize {
300        (*self).pack_sz()
301    }
302
303    fn pack(&self, out: &mut [u8]) {
304        (*self).pack(out)
305    }
306}
307
308////////////////////////////// Packable/Unpackable for sized integers //////////////////////////////
309
310macro_rules! packable_with_to_le_bytes {
311    ($what:ty) => {
312        impl Packable for $what {
313            fn pack_sz(&self) -> usize {
314                self.to_le_bytes().len()
315            }
316
317            fn pack(&self, out: &mut [u8]) {
318                let b = &self.to_le_bytes();
319                assert_eq!(b.len(), out.len());
320                out.copy_from_slice(b);
321            }
322        }
323
324        impl<'a> Unpackable<'a> for $what {
325            type Error = Error;
326
327            fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Error> {
328                const SZ: usize = std::mem::size_of::<$what>();
329                if buf.len() >= SZ {
330                    let mut fbuf: [u8; SZ] = [0; SZ];
331                    fbuf.copy_from_slice(&buf[0..SZ]);
332                    Ok((<$what>::from_le_bytes(fbuf), &buf[SZ..]))
333                } else {
334                    Err(Error::BufferTooShort {
335                        required: SZ,
336                        had: buf.len(),
337                    })
338                }
339            }
340        }
341    };
342}
343
344packable_with_to_le_bytes!(i8);
345packable_with_to_le_bytes!(u8);
346
347packable_with_to_le_bytes!(i16);
348packable_with_to_le_bytes!(u16);
349
350packable_with_to_le_bytes!(i32);
351packable_with_to_le_bytes!(u32);
352
353packable_with_to_le_bytes!(i64);
354packable_with_to_le_bytes!(u64);
355
356/////////////////////////////// Packable/Unpackable for sized floats ///////////////////////////////
357
358// NOTE(rescrv): I tried to dedupe this macro from the above.  Whether I made a typo or there's
359// something deeper here, I exceeded half the time it takes to copy and dupe the tests, so that's
360// the path I'm taking.  Suggestions to dedupe (that do not change the tests) are welcome!
361macro_rules! packable_with_to_bits_to_le_bytes {
362    ($what:ty, $indirect:ty) => {
363        impl Packable for $what {
364            fn pack_sz(&self) -> usize {
365                self.to_bits().to_le_bytes().len()
366            }
367
368            fn pack(&self, out: &mut [u8]) {
369                let b = &self.to_bits().to_le_bytes();
370                assert_eq!(b.len(), out.len());
371                out.copy_from_slice(b);
372            }
373        }
374        impl<'a> Unpackable<'a> for $what {
375            type Error = Error;
376
377            fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Error> {
378                const SZ: usize = std::mem::size_of::<$what>();
379                if buf.len() >= SZ {
380                    let mut fbuf: [u8; SZ] = [0; SZ];
381                    fbuf.copy_from_slice(&buf[0..SZ]);
382                    Ok((
383                        <$what>::from_bits(<$indirect>::from_le_bytes(fbuf)),
384                        &buf[SZ..],
385                    ))
386                } else {
387                    Err(Error::BufferTooShort {
388                        required: SZ,
389                        had: buf.len(),
390                    })
391                }
392            }
393        }
394    };
395}
396
397packable_with_to_bits_to_le_bytes!(f32, u32);
398packable_with_to_bits_to_le_bytes!(f64, u64);
399
400//////////////////////////////////////// Packable/Unpackable ///////////////////////////////////////
401
402impl Packable for char {
403    fn pack_sz(&self) -> usize {
404        (*self as u32).pack_sz()
405    }
406
407    fn pack(&self, out: &mut [u8]) {
408        (*self as u32).pack(out)
409    }
410}
411
412impl<'a> Unpackable<'a> for char {
413    type Error = Error;
414
415    fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(char, &'b [u8]), Error> {
416        let (c, buf) = u32::unpack(buf)?;
417        if let Some(c) = char::from_u32(c) {
418            Ok((c, buf))
419        } else {
420            Err(Error::NotAChar { value: c })
421        }
422    }
423}
424
425//////////////////////////////////////////// length_free ///////////////////////////////////////////
426
427/// Pack a byte slice without a length prefix.  The resulting format is equivalent to concatenating
428/// the individual packings.
429pub fn length_free<P: Packable>(slice: &[P]) -> LengthFree<'_, P> {
430    LengthFree { slice }
431}
432
433/// A type that packs a slice of objects by concatenating their packed representations.  Does not
434/// prepend a length.
435pub struct LengthFree<'a, P: Packable> {
436    slice: &'a [P],
437}
438
439impl<P: Packable> Packable for LengthFree<'_, P> {
440    fn pack_sz(&self) -> usize {
441        self.slice.iter().map(|x| x.pack_sz()).sum()
442    }
443
444    fn pack(&self, out: &mut [u8]) {
445        let mut out = out;
446        for i in 0..self.slice.len() {
447            out = pack_helper(&self.slice[i], out);
448        }
449    }
450}
451
452////////////////////////////////////////// LengthPrefixer //////////////////////////////////////////
453
454/// A type that packs a slice of objects by concatenating their packed representations.  Prepends a
455/// length.
456pub struct LengthPrefixer<'a, P>
457where
458    P: Packable + 'a,
459{
460    // memoized body.pack_sz
461    size: usize,
462    body: &'a P,
463}
464
465impl<'a, P> Packable for LengthPrefixer<'a, P>
466where
467    P: Packable + 'a,
468{
469    fn pack_sz(&self) -> usize {
470        let vsz: v64 = self.size.into();
471        vsz.pack_sz() + self.size
472    }
473
474    fn pack(&self, out: &mut [u8]) {
475        let vsz: v64 = self.size.into();
476        let (prefix, suffix): (&mut [u8], &mut [u8]) = out.split_at_mut(vsz.pack_sz());
477        vsz.pack(prefix);
478        self.body.pack(suffix);
479    }
480}
481
482/////////////////////////////////////////////// &[u8] //////////////////////////////////////////////
483
484impl Packable for &[u8] {
485    fn pack_sz(&self) -> usize {
486        let vsz: v64 = self.len().into();
487        vsz.pack_sz() + self.len()
488    }
489
490    fn pack(&self, out: &mut [u8]) {
491        let vsz: v64 = self.len().into();
492        let (prefix, suffix): (&mut [u8], &mut [u8]) = out.split_at_mut(vsz.pack_sz());
493        vsz.pack(prefix);
494        suffix.copy_from_slice(self);
495    }
496}
497
498impl<'a> Unpackable<'a> for &'a [u8] {
499    type Error = Error;
500
501    fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Error> {
502        let (vsz, buf): (v64, &'b [u8]) = v64::unpack(buf)?;
503        let x: usize = vsz.into();
504        if x > buf.len() {
505            Err(Error::BufferTooShort {
506                required: x,
507                had: buf.len(),
508            })
509        } else {
510            Ok((&buf[0..x], &buf[x..]))
511        }
512    }
513}
514
515////////////////////////////// Packable/Unpackable for n-tuple, n > 1 //////////////////////////////
516
517macro_rules! impl_pack_unpack_tuple {
518    () => {
519        impl Packable for () {
520            fn pack_sz(&self) -> usize {
521                0
522            }
523
524            fn pack(&self, _: &mut [u8]) {}
525        }
526
527        impl<'a> Unpackable<'a> for () {
528            type Error = Error;
529
530            fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Error> {
531                Ok(((), buf))
532            }
533        }
534    };
535    ( $($name:ident)+ ) => {
536        #[allow(non_snake_case)]
537        impl<$($name: Packable),+> Packable for ($($name,)+) {
538            fn pack_sz(&self) -> usize {
539                let ($(ref $name,)+) = *self;
540                $($name.pack_sz() + )+ /* expansion ended with "+" */ 0
541            }
542
543            fn pack(&self, buf: &mut[u8]) {
544                let ($(ref $name,)+) = *self;
545                let pa = stack_pack(());
546                $(let pa = pa.pack($name);)+
547                pa.into_slice(buf);
548            }
549        }
550
551        #[allow(non_snake_case)]
552        impl<'a, ER: Debug, $($name: Unpackable<'a, Error=ER> + 'a),+> Unpackable<'a> for ($($name,)+) {
553            type Error = ER;
554
555            fn unpack<'b: 'a>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Self::Error> {
556                let mut up: Unpacker<'b> = Unpacker::new(buf);
557                $(let $name = up.unpack()?;)+
558                let rem: &'b [u8] = up.remain();
559                Ok((($($name,)+), rem))
560            }
561        }
562    };
563}
564
565impl_pack_unpack_tuple! {}
566
567impl_pack_unpack_tuple! { A }
568impl_pack_unpack_tuple! { A B }
569impl_pack_unpack_tuple! { A B C }
570impl_pack_unpack_tuple! { A B C D }
571impl_pack_unpack_tuple! { A B C D E }
572impl_pack_unpack_tuple! { A B C D E F }
573impl_pack_unpack_tuple! { A B C D E F G }
574impl_pack_unpack_tuple! { A B C D E F G H }
575impl_pack_unpack_tuple! { A B C D E F G H I }
576impl_pack_unpack_tuple! { A B C D E F G H I J }
577impl_pack_unpack_tuple! { A B C D E F G H I J K }
578impl_pack_unpack_tuple! { A B C D E F G H I J K L }
579impl_pack_unpack_tuple! { A B C D E F G H I J K L M }
580impl_pack_unpack_tuple! { A B C D E F G H I J K L M N }
581impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O }
582impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P }
583impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q }
584impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R }
585impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S }
586impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T }
587impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T U }
588impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T U V }
589impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W }
590impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X }
591impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X Y }
592impl_pack_unpack_tuple! { A B C D E F G H I J K L M N O P Q R S T U V W X Y Z }
593
594////////////////////////////////////////////// Result //////////////////////////////////////////////
595
596impl<T: Packable, E: Packable> Packable for Result<T, E> {
597    fn pack_sz(&self) -> usize {
598        match self {
599            Ok(x) => stack_pack(v64::from(10))
600                .pack(v64::from(x.pack_sz()))
601                .pack(x)
602                .pack_sz(),
603            Err(e) => stack_pack(v64::from(18))
604                .pack(v64::from(e.pack_sz()))
605                .pack(e)
606                .pack_sz(),
607        }
608    }
609
610    fn pack(&self, out: &mut [u8]) {
611        match self {
612            Ok(x) => {
613                stack_pack(v64::from(10))
614                    .pack(v64::from(x.pack_sz()))
615                    .pack(x)
616                    .into_slice(out);
617            }
618            Err(e) => {
619                stack_pack(v64::from(18))
620                    .pack(v64::from(e.pack_sz()))
621                    .pack(e)
622                    .into_slice(out);
623            }
624        }
625    }
626}
627
628impl<'a, T, E> Unpackable<'a> for Result<T, E>
629where
630    T: Unpackable<'a>,
631    E: Unpackable<'a>
632        + Debug
633        + From<Error>
634        + From<<T as Unpackable<'a>>::Error>
635        + From<<E as Unpackable<'a>>::Error>,
636{
637    type Error = E;
638
639    fn unpack<'b>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Self::Error>
640    where
641        'b: 'a,
642    {
643        let mut up = Unpacker::new(buf);
644        let tag: v64 = up.unpack()?;
645        if <v64 as Into<u64>>::into(tag) > u32::MAX as u64 {
646            return Err(Error::TagTooLarge { tag: tag.into() }.into());
647        }
648        let tag: u32 = tag.try_into().unwrap();
649        match tag {
650            10 => {
651                let x: v64 = up.unpack()?;
652                let buf: &[u8] = &up.remain()[..x.into()];
653                up.advance(x.into());
654                let (t, _): (T, _) = <T as Unpackable>::unpack(buf)?;
655                Ok((Ok(t), up.remain()))
656            }
657            18 => {
658                let x: v64 = up.unpack()?;
659                let buf: &[u8] = &up.remain()[..x.into()];
660                up.advance(x.into());
661                let (e, _): (E, _) = <E as Unpackable>::unpack(buf)?;
662                Ok((Err(e), up.remain()))
663            }
664            _ => Err(Error::UnknownDiscriminant { discriminant: tag }.into()),
665        }
666    }
667}
668
669///////////////////////////////////////////// mod tests ////////////////////////////////////////////
670
671#[cfg(test)]
672mod tests {
673    use super::*;
674
675    #[test]
676    fn pack_void() {
677        let buf: &mut [u8; 0] = &mut [];
678        ().pack(buf);
679        let mut up = Unpacker::new(buf);
680        let x: Result<(), Error> = up.unpack();
681        assert_eq!(Ok(()), x, "human got decode wrong?");
682        assert_eq!(0, up.buf.len(), "human got remainder wrong?");
683    }
684
685    macro_rules! test_pack_with_to_le_bytes {
686        ($what:ty, $num:expr, $x:expr, $human:expr) => {{
687            const HUMAN: &[u8] = $human;
688            const X: $what = $x as $what;
689            const LEN: usize = $num;
690            let exp = &X.to_le_bytes();
691            assert_eq!(HUMAN, exp, "human got test vector wrong?");
692            assert_eq!(LEN, exp.len(), "human got test vector wrong?");
693            {
694                let buf: &mut [u8; LEN] = &mut <[u8; LEN]>::default();
695                X.pack(buf);
696                assert_eq!(exp, buf, "human got implementation wrong?");
697                assert_eq!(HUMAN, buf, "human got test macro wrong?");
698            }
699            {
700                let mut up = Unpacker::new(HUMAN);
701                let x = up.unpack();
702                let expect: Result<$what, Error> = Ok(X);
703                assert_eq!(expect, x, "human got implementation wrong?");
704                assert_eq!(0, up.buf.len(), "human got remainder wrong?");
705            }
706        }};
707    }
708
709    #[test]
710    fn pack_and_unpack_integers() {
711        // don't want human error, so want to automate test
712        // don't know how to test the testing automation
713        // be a bit verbose and do both, checking all three
714        test_pack_with_to_le_bytes!(u8, 1, 0xc0u8, &[0xc0]);
715        test_pack_with_to_le_bytes!(i8, 1, 0xc0u8, &[0xc0]);
716        test_pack_with_to_le_bytes!(u16, 2, 0xc0ffu16, &[0xff, 0xc0]);
717        test_pack_with_to_le_bytes!(i16, 2, 0xc0ffu16, &[0xff, 0xc0]);
718        test_pack_with_to_le_bytes!(i32, 4, 0xc0ffeedau32, &[0xda, 0xee, 0xff, 0xc0]);
719        test_pack_with_to_le_bytes!(u32, 4, 0xc0ffeedau32, &[0xda, 0xee, 0xff, 0xc0]);
720        test_pack_with_to_le_bytes!(
721            i64,
722            8,
723            0xc0ffeeda7e11f00du64,
724            &[0x0d, 0xf0, 0x11, 0x7e, 0xda, 0xee, 0xff, 0xc0]
725        );
726        test_pack_with_to_le_bytes!(
727            u64,
728            8,
729            0xc0ffeeda7e11f00du64,
730            &[0x0d, 0xf0, 0x11, 0x7e, 0xda, 0xee, 0xff, 0xc0]
731        );
732    }
733
734    macro_rules! test_pack_with_to_bits_to_le_bytes {
735        ($what:ty, $num:expr, $x:expr, $human:expr) => {{
736            const HUMAN: &[u8] = $human;
737            const X: $what = $x as $what;
738            const LEN: usize = $num;
739            let exp = &X.to_bits().to_le_bytes();
740            assert_eq!(HUMAN, exp, "human got test vector wrong?");
741            assert_eq!(LEN, exp.len(), "human got test vector wrong?");
742            {
743                let buf: &mut [u8; LEN] = &mut <[u8; LEN]>::default();
744                X.pack(buf);
745                assert_eq!(exp, buf, "human got implementation wrong?");
746                assert_eq!(HUMAN, buf, "human got test macro wrong?");
747            }
748            {
749                let mut up = Unpacker::new(HUMAN);
750                let x = up.unpack();
751                let expect: Result<$what, Error> = Ok(X);
752                assert_eq!(expect, x, "human got implementation wrong?");
753                assert_eq!(0, up.buf.len(), "human got remainder wrong?");
754            }
755        }};
756    }
757
758    #[test]
759    fn pack_and_unpack_floats() {
760        test_pack_with_to_bits_to_le_bytes!(f32, 4, 16711938.0, &[0x02, 0x01, 0x7f, 0x4b]);
761        test_pack_with_to_bits_to_le_bytes!(
762            f64,
763            8,
764            9006104071832581.0,
765            &[0x05, 0x04, 0x03, 0x02, 0x01, 0xff, 0x3f, 0x43]
766        );
767    }
768
769    #[test]
770    fn split_tuple() {
771        // Inspired by a bug where the unpacker was told to return &'static [] so that it would
772        // pass the type checker.  Need a test that has tuple with remainder as it's not the
773        // typical, or even expected case.
774        let (a, b, c, d) = (42u8, 13u8, 73u8, 32u8);
775        let mut buf = [0u8; 4];
776        (a, b, c, d).pack(&mut buf);
777        assert_eq!([a, b, c, d], buf, "human got serialization wrong?");
778        let mut up = Unpacker::new(&buf);
779        let (ap, bp): (u8, u8) = up.unpack().unwrap();
780        let (cp, dp): (u8, u8) = up.unpack().unwrap();
781        assert_eq!(
782            [a, b, c, d],
783            [ap, bp, cp, dp],
784            "human got deserialization wrong?"
785        );
786    }
787
788    #[test]
789    fn length_free() {
790        let buf = &mut [0u8; 64];
791        let buf = stack_pack(super::length_free(&[0u8, 1u8, 2u8])).into_slice(buf);
792        assert_eq!([0, 1, 2], buf, "human got length_free wrong?");
793    }
794
795    #[test]
796    fn stack_pack_into_slice() {
797        let buf = &mut [0u8; 64];
798        let buf = stack_pack(42u64).into_slice(buf);
799        assert_eq!(
800            &[42, 0, 0, 0, 0, 0, 0, 0],
801            buf,
802            "human got into_slice wrong?"
803        );
804    }
805
806    #[test]
807    fn stack_pack_to_vec() {
808        let buf: &[u8] = &stack_pack(42u64).to_vec();
809        assert_eq!(&[42, 0, 0, 0, 0, 0, 0, 0], &buf, "human got to_vec wrong?");
810    }
811
812    #[test]
813    fn stack_packer() {
814        let pa = stack_pack(());
815        let pa = pa.pack(1u8);
816        let pa = pa.pack(770u16);
817        let pa = pa.pack(117835012u32);
818        let pa = pa.pack(1084818905618843912u64);
819        let mut buf = [0u8; 16];
820        let buf = pa.into_slice(&mut buf);
821        assert_eq!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], buf);
822    }
823
824    #[test]
825    fn unpacker() {
826        let buf: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
827        let mut up = Unpacker::new(buf);
828        let x = up.unpack::<Error, ()>();
829        assert_eq!(Ok(()), x, "human got () unpacker wrong?");
830        let x = up.unpack::<Error, u8>();
831        assert_eq!(Ok(1u8), x, "human got u8 unpacker wrong?");
832        let x = up.unpack::<Error, u16>();
833        assert_eq!(Ok(770u16), x, "human got u16 unpacker wrong?");
834        let x = up.unpack::<Error, u32>();
835        assert_eq!(Ok(117835012u32), x, "human got u32 unpacker wrong?");
836        let x = up.unpack::<Error, u64>();
837        assert_eq!(
838            Ok(1084818905618843912u64),
839            x,
840            "human got u64 unpacker wrong?"
841        );
842        assert_eq!(&[] as &[u8], up.buf, "human got remaining buffer wrong?");
843    }
844
845    #[test]
846    fn pack_and_unpack_slice() {
847        let buf: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
848        let pa = stack_pack(buf);
849        let exp: &[u8] = &[16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
850        let got: &[u8] = &pa.to_vec();
851        assert_eq!(exp, got);
852        let mut up = Unpacker::new(exp);
853        let got: &[u8] = up.unpack().expect("unpack slice");
854        assert_eq!(buf, got);
855    }
856}