binmarshal/
lib.rs

1#![cfg_attr(not(feature="std"), no_std)]
2
3#![doc = include_str!("../README.md")]
4
5extern crate alloc;
6
7pub mod rw;
8pub mod numeric;
9
10use bounded_static::{IntoBoundedStatic, ToBoundedStatic};
11pub use rw::*;
12pub use numeric::*;
13
14use core::{ops::{Deref, DerefMut}, result::Result, mem::MaybeUninit, marker::PhantomData, borrow::Borrow};
15
16use alloc::{string::String, borrow::Cow, borrow::ToOwned, vec::Vec};
17
18pub use binmarshal_macros::{Marshal, Demarshal, MarshalUpdate, Proxy};
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 
22#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
23pub enum MarshalError {
24  BufferTooSmall,
25  IllegalValue {
26    byte_offset: usize,
27    bit_offset: usize,
28  },
29  IllegalTag,
30  CoercionError,
31  ExpectedSentinel,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct BitSpecification<const BITS: usize>;
36
37pub trait Marshal<Context = ()> {
38  fn write<W: BitWriter>(&self, writer: &mut W, ctx: Context) -> Result<(), MarshalError>;
39}
40
41pub trait Demarshal<'dm, Context = ()> : Sized {
42  fn read(view: &mut BitView<'dm>, ctx: Context) -> Result<Self, MarshalError>;
43}
44
45impl<'a, C, T: Marshal<C> + ?Sized> Marshal<C> for &'a T {
46  fn write<W: BitWriter>(&self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
47    (self as &'a T).write(writer, ctx)
48  }
49}
50// Stolen mercilessly from serde
51pub trait DemarshalOwned<Context = ()> : for<'de> Demarshal<'de, Context> {}
52impl<T, Context> DemarshalOwned<Context> for T where T: for<'de> Demarshal<'de, Context> {}
53
54pub trait MarshalUpdate<Context = ()> : Sized {
55  fn update(&mut self, ctx: &mut Context);
56}
57
58impl Marshal<()> for () {
59  #[inline(always)]
60  fn write<W: BitWriter>(&self, _writer: &mut W, _ctx: ()) -> Result<(), MarshalError> {
61    Ok(())
62  }
63}
64
65impl<'dm> Demarshal<'dm, ()> for () {
66  #[inline(always)]
67  fn read(_view: &mut BitView<'dm>, _ctx: ()) -> Result<Self, MarshalError> {
68    Ok(())
69  }
70}
71
72impl<C: Clone, T: Marshal<C>, const N: usize> Marshal<C> for [T; N] {
73  #[inline]
74  fn write<W: BitWriter>(&self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
75    for v in self.iter() {
76      v.write(writer, ctx.clone())?;
77    }
78    Ok(())
79  }
80}
81
82impl<'dm, C: Clone, T: Demarshal<'dm, C>, const N: usize> Demarshal<'dm, C> for [T; N] {
83  fn read(view: &mut BitView<'dm>, ctx: C) -> Result<Self, MarshalError> {
84    let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
85    for i in 0..N {
86      arr[i] = MaybeUninit::new(T::read(view, ctx.clone())?);
87    }
88    return unsafe { Ok(arr.as_ptr().cast::<[T; N]>().read()) }
89  }
90}
91
92#[derive(Proxy)]
93pub struct Buffer<const N: usize>(pub [u8; N]);
94
95impl<const N: usize> Marshal<()> for Buffer<N> {
96  fn write<W: BitWriter>(&self, writer: &mut W, _ctx: ()) -> Result<(), MarshalError> {
97    writer.align(1);
98    let (arr, _offset) = writer.reserve_and_advance::<N>(N, 0)?;
99    arr.copy_from_slice(&self.0[..]);
100    Ok(())
101  }
102}
103
104impl<'dm, const N: usize> Demarshal<'dm, ()> for Buffer<N> {
105  fn read(view: &mut BitView<'dm>, _ctx: ()) -> Result<Self, MarshalError> {
106    view.align(1);
107    view.take::<N>(N, 0).map(|x| Self(x.0.clone()))
108  }
109}
110
111impl Marshal<()> for String {
112  fn write<W: BitWriter>(&self, writer: &mut W, _ctx: ()) -> Result<(), MarshalError> {
113    writer.align(1);
114    let arr = writer.reserve_and_advance_aligned_slice(self.len() + 1)?;
115    let arr_str_bytes = &mut arr[0..self.len()];
116    arr_str_bytes.copy_from_slice(&self.as_bytes()[..]);
117    arr[arr.len() - 1] = 0;
118    Ok(())
119  }
120}
121
122impl<'de> Demarshal<'de, ()> for String {
123  fn read(view: &mut BitView<'de>, _ctx: ()) -> Result<Self, MarshalError> {
124    let buf = view.take_until(0u8)?;
125
126    unsafe {
127      Ok(String::from_utf8_unchecked(buf.to_vec()))
128    }
129  }
130}
131
132impl Marshal<()> for str {
133  fn write<W: BitWriter>(&self, writer: &mut W, _ctx: ()) -> Result<(), MarshalError> {
134    let arr = writer.reserve_and_advance_aligned_slice(self.len() + 1)?;
135    arr[0..self.len()].copy_from_slice(&self.as_bytes()[..]);
136    arr[arr.len() - 1] = 0;
137    Ok(())
138  }
139}
140
141impl<'dm> Demarshal<'dm, ()> for &'dm str {
142  fn read(view: &mut BitView<'dm>, _ctx: ()) -> Result<Self, MarshalError> {
143    let buf = view.take_until(0u8)?;
144    Ok(unsafe { core::str::from_utf8_unchecked(buf) })
145  }
146}
147
148impl<T: Marshal<()>, E: Marshal<()>> Marshal<()> for core::result::Result<T, E> {
149  fn write<W: BitWriter>(&self, writer: &mut W, _ctx: ()) -> Result<(), MarshalError> {
150    // We need this for alignment on the LaserCAN, due to a mistake in the 0.1.0 bootloader.
151    #[cfg(feature = "lasercan_nop_patch")]
152    unsafe { core::arch::asm!("nop") }
153
154    match self {
155      Ok(ok) => {
156        0u8.write(writer, ())?;
157        ok.write(writer, ())
158      },
159      Err(err) => {
160        1u8.write(writer, ())?;
161        err.write(writer, ())
162      },
163    }
164  }
165}
166
167impl<'dm, T: Demarshal<'dm, ()>, E: Demarshal<'dm, ()>> Demarshal<'dm, ()> for core::result::Result<T, E> {
168  fn read(view: &mut BitView<'dm>, _ctx: ()) -> Result<Self, MarshalError> {
169    let tag = u8::read(view, ())?;
170    match tag {
171      0 => {
172        T::read(view, ()).map(Ok)
173      },
174      _ => {
175        E::read(view, ()).map(Err)
176      },
177    }
178  }
179}
180
181// [T] and Vec<T> are both all-consuming. [u8] and Vec<u8> are special cases if using Payload and LengthTaggedPayload.
182impl<'a, C: Clone, T: Marshal<C>> Marshal<C> for [T] {
183  fn write<W: BitWriter>(&self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
184    // let arr = writer.reserve_and_advance_aligned_slice(self.len())?;
185    // arr.copy_from_slice(self);
186    // Ok(())
187    for result in self.iter().map(|x| x.write(writer, ctx.clone())) {
188      result?;
189    }
190    Ok(())
191  }
192}
193
194impl<'a, C: Clone, T: Marshal<C>> Marshal<C> for Vec<T> {
195  fn write<W: BitWriter>(&self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
196    for result in self.iter().map(|x| x.write(writer, ctx.clone())) {
197      result?;
198    }
199    Ok(())
200  }
201}
202
203impl<'dm, C: Clone, T: Demarshal<'dm, C>> Demarshal<'dm, C> for Vec<T> {
204  fn read(view: &mut BitView<'dm>, ctx: C) -> Result<Self, MarshalError> {
205    let mut v = Vec::new();
206
207    loop {
208      match T::read(view, ctx.clone()) {
209        Ok(t) => v.push(t),
210        Err(MarshalError::BufferTooSmall) => break,
211        Err(e) => Err(e)?
212      }
213    }
214
215    Ok(v)
216  }
217}
218
219macro_rules! make_referent {
220  ($referent_name:ident, $owned_name:ident, $inner:ty, <$($generics:ident),*>) => {
221    #[repr(transparent)]
222    pub struct $referent_name <$($generics),*> {
223      #[allow(unused_parens)]
224      phantoms: PhantomData<($($generics),*)>,
225      inner: $inner
226    }
227
228    pub struct $owned_name <$($generics),*> where $inner: ToOwned {
229      #[allow(unused_parens)]
230      phantoms: PhantomData<($($generics),*)>,
231      inner: <$inner as ToOwned>::Owned
232    }
233
234    impl<$($generics),*> $owned_name<$($generics),*> where $inner: ToOwned {
235      pub fn new(inner: <$inner as ToOwned>::Owned) -> Self {
236        Self { phantoms: PhantomData, inner }
237      }
238    }
239
240    impl<'a, $($generics),*> From<&'a $inner> for &'a $referent_name <$($generics),*> {
241      fn from(r: &'a $inner) -> Self {
242        let ptr = r as *const $inner as *const $referent_name <$($generics),*>;
243        unsafe { &*ptr }
244      }
245    }
246
247    impl<'a, $($generics),*> AsRef<$inner> for &'a $referent_name <$($generics),*> {
248      fn as_ref(&self) -> &'a $inner {
249        &self.inner
250      }
251    }
252
253    impl<$($generics),*> Deref for $referent_name <$($generics),*> {
254      type Target = $inner;
255
256      fn deref(&self) -> &Self::Target {
257        &self.inner
258      }
259    }
260
261    impl<$($generics),*> Deref for $owned_name <$($generics),*> where $inner: ToOwned {
262      type Target = <$inner as ToOwned>::Owned;
263
264      fn deref(&self) -> &Self::Target {
265        &self.inner
266      }
267    }
268
269    impl<$($generics),*> DerefMut for $owned_name <$($generics),*> where $inner: ToOwned {
270      fn deref_mut(&mut self) -> &mut Self::Target {
271        &mut self.inner
272      }
273    }
274
275    impl<$($generics),*> Clone for $owned_name <$($generics),*> where $inner: ToOwned, <$inner as ToOwned>::Owned: Clone {
276      fn clone(&self) -> Self { Self { phantoms: PhantomData, inner: self.inner.clone() } }
277    }
278    
279    impl<$($generics),*> core::fmt::Debug for $referent_name <$($generics),*> where $inner: core::fmt::Debug {
280      fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.inner.fmt(f) }
281    }
282
283    impl<$($generics),*> core::fmt::Debug for $owned_name <$($generics),*> where $inner: ToOwned, <$inner as ToOwned>::Owned: core::fmt::Debug {
284      fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.inner.fmt(f) }
285    }
286
287    impl<$($generics),*> PartialEq for $referent_name <$($generics),*> where $inner: PartialEq {
288      #[inline]
289      fn eq(&self, other: &Self) -> bool {
290          PartialEq::eq(&self.inner, &other.inner)
291      }
292      #[inline]
293      fn ne(&self, other: &Self) -> bool {
294          PartialEq::ne(&self.inner, &other.inner)
295      }
296    }
297
298    impl<$($generics),*> PartialEq for $owned_name <$($generics),*> where $inner: ToOwned, <$inner as ToOwned>::Owned: PartialEq {
299      #[inline]
300      fn eq(&self, other: &Self) -> bool {
301          PartialEq::eq(&self.inner, &other.inner)
302      }
303      #[inline]
304      fn ne(&self, other: &Self) -> bool {
305          PartialEq::ne(&self.inner, &other.inner)
306      }
307    }
308
309    impl<$($generics),*> Borrow<$referent_name <$($generics),*>> for $owned_name <$($generics),*> where $inner: ToOwned {
310      fn borrow<'a>(&'a self) -> &'a $referent_name<$($generics),*> {
311        let ptr = Borrow::borrow(&self.inner) as *const $inner as *const $referent_name <$($generics),*>;
312        unsafe { &*ptr }
313      }
314    }
315
316    impl<$($generics),*> ToOwned for $referent_name <$($generics),*> where $inner: ToOwned {
317      type Owned = $owned_name <$($generics),*>;
318
319      fn to_owned(&self) -> Self::Owned {
320        $owned_name { phantoms: PhantomData, inner: self.inner.to_owned() }
321      }
322    }
323
324    impl<CTX, $($generics),*> Marshal<CTX> for $owned_name <$($generics),*> where $inner: ToOwned, $referent_name<$($generics),*>: Marshal<CTX> {
325      fn write<W: BitWriter>(&self, writer: &mut W, ctx: CTX) -> Result<(), MarshalError> {
326        Marshal::<CTX>::write(Borrow::<$referent_name <$($generics),*>>::borrow(self), writer, ctx)
327      }
328    }
329
330    #[cfg(feature = "serde")]
331    impl<$($generics),*> serde::Serialize for $referent_name<$($generics),*> where $inner: serde::Serialize {
332      fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
333      where
334        S: serde::Serializer
335      {
336        self.inner.serialize(serializer)
337      }
338    }
339
340    #[cfg(feature = "serde")]
341    impl<$($generics),*> serde::Serialize for $owned_name<$($generics),*> where $inner: ToOwned + serde::Serialize {
342      fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
343      where
344        S: serde::Serializer
345      {
346        Borrow::<$referent_name <$($generics),*>>::borrow(self).serialize(serializer)
347      }
348    }
349
350    #[cfg(feature = "serde")]
351    impl<'de, $($generics),*> serde::de::Deserialize<'de> for $owned_name<$($generics),*> where $inner: ToOwned, <$inner as ToOwned>::Owned: serde::de::Deserialize<'de> {
352      fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
353      where
354        D: serde::Deserializer<'de>
355      {
356        let t = <$inner as ToOwned>::Owned::deserialize(deserializer)?;
357        Ok(Self { phantoms: PhantomData, inner: t })
358      }
359    }
360
361    #[cfg(feature = "schema")]
362    impl<$($generics),*> schemars::JsonSchema for $referent_name<$($generics),*> where $inner: schemars::JsonSchema {
363      fn schema_name() -> String {
364        <$inner>::schema_name()
365      }
366
367      fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
368        <$inner>::json_schema(gen)
369      }
370
371      fn is_referenceable() -> bool {
372        <$inner>::is_referenceable()
373      }
374
375      fn schema_id() -> Cow<'static, str> {
376        <$inner>::schema_id()
377      }
378    }
379
380    #[cfg(feature = "schema")]
381    impl<$($generics),*> schemars::JsonSchema for $owned_name<$($generics),*> where $inner: ToOwned, <$inner as ToOwned>::Owned: schemars::JsonSchema {
382      fn schema_name() -> String {
383        <$inner as ToOwned>::Owned::schema_name()
384      }
385
386      fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
387        <$inner as ToOwned>::Owned::json_schema(gen)
388      }
389
390      fn is_referenceable() -> bool {
391        <$inner as ToOwned>::Owned::is_referenceable()
392      }
393
394      fn schema_id() -> Cow<'static, str> {
395        <$inner as ToOwned>::Owned::schema_id()
396      }
397    }
398  };
399}
400
401make_referent!(Payload, PayloadOwned, [u8], <>);
402make_referent!(LengthTaggedPayload, LengthTaggedPayloadOwned, [u8], <L>);
403make_referent!(LengthTaggedSlice, LengthTaggedVec, [T], <L, T>);
404
405impl Marshal<()> for Payload {
406  fn write<W: BitWriter>(&self, writer: &mut W, _: ()) -> Result<(), MarshalError> {
407    let arr = writer.reserve_and_advance_aligned_slice(self.inner.len())?;
408    arr.copy_from_slice(&self.inner);
409    Ok(())
410  }
411}
412
413impl<'dm> Demarshal<'dm, ()> for &'dm Payload {
414  fn read(view: &mut BitView<'dm>, _: ()) -> Result<Self, MarshalError> {
415    view.take_remaining().map(Into::into)
416  }
417}
418
419impl<'dm> Demarshal<'dm, ()> for PayloadOwned {
420  fn read(view: &mut BitView<'dm>, _: ()) -> Result<Self, MarshalError> {
421    let m = view.take_remaining()?;
422    Ok(PayloadOwned::new(m.to_vec()))
423  }
424}
425
426impl<L: TryFrom<usize> + Marshal<()>> Marshal<()> for LengthTaggedPayload<L> {
427  fn write<W: BitWriter>(&self, writer: &mut W, _: ()) -> Result<(), MarshalError> {
428    match L::try_from(self.inner.len()) {
429      Ok(v) => {
430        v.write(writer, ())?;
431        let arr = writer.reserve_and_advance_aligned_slice(self.inner.len())?;
432        arr.copy_from_slice(&self.inner);
433        Ok(())
434      },
435      Err(_) => Err(MarshalError::CoercionError),
436    }
437  }
438}
439
440impl<'dm, L: TryInto<usize> + DemarshalOwned> Demarshal<'dm, ()> for &'dm LengthTaggedPayload<L> {
441  fn read(view: &mut BitView<'dm>, _: ()) -> Result<Self, MarshalError> {
442    let l = L::read(view, ())?;
443    let as_usize = l.try_into().map_err(|_| MarshalError::CoercionError)?;
444    view.take_aligned_slice(as_usize).map(Into::into)
445  }
446}
447
448impl<'dm, L: TryInto<usize> + DemarshalOwned> Demarshal<'dm, ()> for LengthTaggedPayloadOwned<L> {
449  fn read(view: &mut BitView<'dm>, _: ()) -> Result<Self, MarshalError> {
450    let l = L::read(view, ())?;
451    let as_usize = l.try_into().map_err(|_| MarshalError::CoercionError)?;
452    Ok(LengthTaggedPayloadOwned::new(view.take_aligned_slice(as_usize)?.to_vec()))
453  }
454}
455
456impl<C: Clone, T: Marshal<C>, L: TryFrom<usize> + Marshal<()>> Marshal<C> for LengthTaggedSlice<L, T> {
457  fn write<W: BitWriter>(&self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
458    match L::try_from(self.inner.len()) {
459      Ok(v) => {
460        v.write(writer, ())?;
461        for result in self.inner.iter().map(|x| x.write(writer, ctx.clone())) {
462          result?;
463        }
464        Ok(())
465      },
466      Err(_) => Err(MarshalError::CoercionError),
467    }
468  }
469}
470
471impl<'dm, C: Clone, T: Demarshal<'dm, C>, L: TryInto<usize> + DemarshalOwned> Demarshal<'dm, C> for LengthTaggedVec<L, T>
472  where [T]: ToOwned<Owned = Vec<T>>
473{
474  fn read(view: &mut BitView<'dm>, ctx: C) -> Result<Self, MarshalError> {
475    let l = L::read(view, ())?;
476    let as_usize = l.try_into().map_err(|_| MarshalError::CoercionError)?;
477    let mut v = Vec::with_capacity(as_usize);
478    for _ in 0..as_usize {
479      v.push(T::read(view, ctx.clone())?);
480    }
481    Ok(LengthTaggedVec::new(v))
482  }
483}
484
485impl<'a, C, T> Marshal<C> for Cow<'a, T>
486where
487  T: ToOwned + ?Sized + Marshal<C>,
488{
489  fn write<'f, W: BitWriter>(&'f self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
490    let borrowed = self as &T;
491    borrowed.write(writer, ctx)
492  }
493}
494
495impl<'a, 'dm, C, T> Demarshal<'dm, C> for Cow<'a, T>
496where
497  T: ToOwned + ?Sized,
498  <T as ToOwned>::Owned: Demarshal<'dm, C>
499{
500  fn read(view: &mut BitView<'dm>, ctx: C) -> Result<Self, MarshalError> {
501    let t = <T as ToOwned>::Owned::read(view, ctx)?;
502    Ok(alloc::borrow::Cow::Owned(t))
503  }
504}
505
506#[derive(Proxy)]
507pub struct AsymmetricCow<'a, T: 'a + ToOwned + ?Sized>(pub Cow<'a, T>);
508
509impl<'a, T: 'a + ToOwned + ?Sized> AsymmetricCow<'a, T> {
510  pub fn into_owned(self) -> <T as ToOwned>::Owned {
511    self.0.into_owned()
512  }
513
514  pub fn to_mut(&mut self) -> &mut <T as ToOwned>::Owned {
515    self.0.to_mut()
516  }
517}
518
519impl<'a, C, T: ToOwned + ?Sized + Marshal<C>> Marshal<C> for AsymmetricCow<'a, T> {
520  fn write<W: BitWriter>(&self, writer: &mut W, ctx: C) -> Result<(), MarshalError> {
521    self.0.write(writer, ctx)
522  }
523}
524
525impl<'dm, C, T> Demarshal<'dm, C> for AsymmetricCow<'dm, T>
526where
527  T: ToOwned + ?Sized + 'dm,
528  &'dm T: Demarshal<'dm, C>
529{
530  fn read(view: &mut BitView<'dm>, ctx: C) -> Result<Self, MarshalError> {
531    let t = <&T>::read(view, ctx)?;
532    Ok(AsymmetricCow(alloc::borrow::Cow::Borrowed(t)))
533  }
534}
535
536impl<'a, T: 'static + ToOwned + ?Sized> IntoBoundedStatic for AsymmetricCow<'a, T> {
537  type Static = AsymmetricCow<'static, T>;
538
539  fn into_static(self) -> Self::Static {
540    AsymmetricCow::<'static, T>(self.0.into_static())
541  }
542}
543
544impl<'a, T: 'static + ToOwned + ?Sized> ToBoundedStatic for AsymmetricCow<'a, T> {
545  type Static = AsymmetricCow<'static, T>;
546
547  fn to_static(&self) -> Self::Static {
548    AsymmetricCow::<'static, T>(self.0.to_static())
549  }
550}
551
552#[cfg(test)]
553mod tests {
554  use crate::*;
555
556  #[test]
557  fn test_u8() {
558    let bytes = [0b1100_0101, 0b1010_0101];
559    let mut reader = BitView::new(&bytes[..]);
560    assert_eq!(u8::read(&mut reader, BitSpecification::<3>), Ok(0b110));
561    assert_eq!(u8::read(&mut reader, ()), Ok(0b0010_1101));
562    assert_eq!(u8::read(&mut reader, BitSpecification::<5>), Ok(0b00101));
563    assert_eq!(u8::read(&mut reader, BitSpecification::<1>), Err(MarshalError::BufferTooSmall));
564
565    let mut out = [0u8; 2];
566    let mut writer = BufferBitWriter::new(&mut out);
567    assert_eq!(0b11001u8.write(&mut writer, BitSpecification::<5>), Ok(()));
568    assert_eq!(0b1010_1101u8.write(&mut writer, BitSpecification::<8>), Ok(()));
569    assert_eq!(0b011u8.write(&mut writer, BitSpecification::<3>), Ok(()));
570    assert_eq!(out[0], 0b1100_1101);
571    assert_eq!(out[1], 0b0110_1011);
572  }
573
574  #[test]
575  fn test_u16() {
576    let bytes = [0b1100_0101, 0b1010_0101, 0b1011_1100];
577    let mut reader = BitView::new(&bytes[..]);
578    assert_eq!(u16::read(&mut reader, BitSpecification::<3>), Ok(0b110));
579    assert_eq!(u16::read(&mut reader, ()), Ok(0b0010_1101_0010_1101));
580    assert_eq!(u8::read(&mut reader, BitSpecification::<5>), Ok(0b11100));
581    assert_eq!(u8::read(&mut reader, BitSpecification::<1>), Err(MarshalError::BufferTooSmall));
582  }
583}