binary_serde/
lib.rs

1//! this is a crate which allows serializing and deserializing rust structs into a packed binary format.
2//!
3//! the format does exactly what you expect it to do, it just serializes all fields in order,
4//! according to their representation in memory, and according to the chosen endianness.
5//!
6//! this is very useful for parsing many common binary formats which often just represent fields in a packed binary representation,
7//! just like the format used by this crate.
8//!
9//! additionally, this crate is very `no_std` friendly and allows writing highly performant code because it allows for knowing
10//! the serialized size of a type as a compile time constant, which means that the type can be serialized into a buffer on
11//! the stack whose size is known at compile time, requiring no heap allocations.
12//!
13//! please note that this means that dynamically sized types like `&[T]`, `Vec<T>` and `String` are not supported.
14//!
15//! ### bitfields
16//!
17//! this crate also supports defining bitfields since those seem to be quite common in a lot of binary formats.
18//! the bitfield definition allows the user to specify the bit length of each field of the struct.
19//! the bitfields are defined using the `binary_serde_bitfield` attribute.
20//! the order of the fields in a bitfield is treated as lsb first.
21//! an example of a bitfield can be seen in the example below.
22//!
23//! ### std support
24//!
25//! this crate provides a feature flag called `std` which enables a bunch of std related features:
26//! - the error types implement `std::error::Error`
27//! - adds the `binary_serialize_into` and the `binary_deserialize_from` functions to the `BinarySerde` trait which allow
28//!   serializing/deserializing to/from data streams (`std::io::Read`/`std::io::Write`).
29//! - adds a bunch of convenience functions and structs which require `std` support.
30//!
31//! # Example
32//! a simple example of serializing and deserializing an elf 32 bit relocation entry:
33//! ```
34//! use binary_serde::{binary_serde_bitfield, BinarySerde, Endianness};
35//!
36//! #[derive(Debug, BinarySerde, Default, PartialEq, Eq)]
37//! #[repr(u8)]
38//! enum Elf32RelocationType {
39//!     #[default]
40//!     Direct = 1,
41//!     PcRelative = 2,
42//!     GotEntry = 3,
43//!     // ...
44//! }
45//!
46//! #[derive(Debug, Default, PartialEq, Eq)]
47//! #[binary_serde_bitfield(order = BitfieldBitOrder::LsbFirst)]
48//! struct Elf32RelocationInfo {
49//!     #[bits(8)]
50//!     ty: Elf32RelocationType,
51//!
52//!     #[bits(24)]
53//!     symbol_index: u32,
54//! }
55//!
56//! #[derive(Debug, BinarySerde, Default, PartialEq, Eq)]
57//! struct Elf32RelocationWithAddend {
58//!     offset: u32,
59//!     info: Elf32RelocationInfo,
60//!     addend: u32,
61//! }
62//!
63//! fn main() {
64//!     let rel = Elf32RelocationWithAddend::default();
65//!
66//!     // serialize the relocation to a statically allocated array on the stack
67//!     let bytes = rel.binary_serialize_to_array(Endianness::Little);
68//!
69//!     // deserialize the relocation from its bytes to get back the original value
70//!     let reconstructed_rel =
71//!         Elf32RelocationWithAddend::binary_deserialize(bytes.as_ref(), Endianness::Little).unwrap();
72//!
73//!     assert_eq!(rel, reconstructed_rel)
74//! }
75//! ```
76
77#![cfg_attr(not(feature = "std"), no_std)]
78
79use core::marker::PhantomData;
80
81pub use binary_serde_macros::{binary_serde_bitfield, BinarySerde};
82use recursive_array::{
83    recursive_array_type_of_size, EmptyRecursiveArray, RecursiveArray, RecursiveArrayMultiplier,
84    RecursiveArraySingleItem,
85};
86
87pub use recursive_array;
88use thiserror_no_std::Error;
89
90/// endianness.
91#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
92pub enum Endianness {
93    Big,
94    Little,
95}
96impl Endianness {
97    #[cfg(target_endian = "little")]
98    pub const NATIVE: Self = Endianness::Little;
99    #[cfg(target_endian = "big")]
100    pub const NATIVE: Self = Endianness::Big;
101}
102
103/// the bit order of a bitfield.
104pub enum BitfieldBitOrder {
105    /// the bitfield is msb first, which means that the bits of the first field will be placed at the msb.
106    MsbFirst,
107
108    /// the bitfield is lsb first, which means that the bits of the first field will be placed at the lsb.
109    LsbFirst,
110}
111
112/// a trait for serializing and deserializing a type into a packed binary format.
113pub trait BinarySerde: Sized {
114    /// the size of this type when serialized to a packed binary format.
115    const SERIALIZED_SIZE: usize;
116
117    /// the fixed size recursive array type that is returned when serializing this type to an array.
118    /// the length of this array is guaranteed to be equal to [`Self::SERIALIZED_SIZE`].
119    type RecursiveArray: RecursiveArray<u8>;
120
121    /// serialize this value into the given buffer using the given endianness.
122    ///
123    /// # Panics
124    ///
125    /// this function panics if the length of `buf` is not exactly equal to [`Self::SERIALIZED_SIZE`].
126    fn binary_serialize(&self, buf: &mut [u8], endianness: Endianness);
127
128    /// serialize this value to a fixed size array using the given endianness.
129    fn binary_serialize_to_array(&self, endianness: Endianness) -> Self::RecursiveArray {
130        let mut array: core::mem::MaybeUninit<Self::RecursiveArray> =
131            core::mem::MaybeUninit::uninit();
132        self.binary_serialize(
133            unsafe {
134                core::slice::from_raw_parts_mut(
135                    array.as_mut_ptr().cast::<u8>(),
136                    Self::SERIALIZED_SIZE,
137                )
138            },
139            endianness,
140        );
141        unsafe { array.assume_init() }
142    }
143
144    #[cfg(feature = "std")]
145    /// serialize this value into the given stream using the given endianness.
146    fn binary_serialize_into<W: std::io::Write>(
147        &self,
148        stream: &mut W,
149        endianness: Endianness,
150    ) -> std::io::Result<()> {
151        let serialized = self.binary_serialize_to_array(endianness);
152        stream.write_all(serialized.as_slice())?;
153        Ok(())
154    }
155
156    /// deserializes the given buffer using the given endianness into a value of this type.
157    ///
158    /// # Errors
159    ///
160    /// this function return an error if the given bytes do not represent a valid value of this type.
161    /// this can only ever happen if during deserialization we got an enum value that does not match any of the enum's variants.
162    ///
163    /// # Panics
164    ///
165    /// this function panics if the length of `buf` is not exactly equal to [`Self::SERIALIZED_SIZE`].
166    fn binary_deserialize(buf: &[u8], endianness: Endianness) -> Result<Self, DeserializeError>;
167
168    #[cfg(feature = "std")]
169    /// deserializes the data from the given stream using the given endianness into a value of this type.
170    fn binary_deserialize_from<R: std::io::Read>(
171        stream: &mut R,
172        endianness: Endianness,
173    ) -> Result<Self, DeserializeFromError> {
174        let mut uninit_array: core::mem::MaybeUninit<Self::RecursiveArray> =
175            core::mem::MaybeUninit::uninit();
176        stream.read_exact(unsafe {
177            core::slice::from_raw_parts_mut(
178                uninit_array.as_mut_ptr().cast::<u8>(),
179                Self::SERIALIZED_SIZE,
180            )
181        })?;
182        let array = unsafe { uninit_array.assume_init() };
183        Ok(Self::binary_deserialize(array.as_slice(), endianness)?)
184    }
185}
186
187/// an error which can occur while deserializing.
188#[derive(Debug, Error)]
189pub enum DeserializeError {
190    #[error("invalid value for enum {enum_name}")]
191    InvalidEnumValue { enum_name: &'static str },
192}
193
194#[cfg(feature = "std")]
195/// an error which can occur while deserializing from a data stream.
196#[derive(Debug, Error)]
197pub enum DeserializeFromError {
198    /// an io error has occured while reading from the stream.
199    #[error("io error while reading from stream")]
200    IoError(
201        #[from]
202        #[source]
203        std::io::Error,
204    ),
205
206    /// a deserialization error occured while trying to deserialize the bytes that were read from the stream.
207    #[error("deserialization error")]
208    DeserializeError(
209        #[from]
210        #[source]
211        DeserializeError,
212    ),
213}
214
215/// an error which can occur while serializing/deserializing to/from a safe buffer serializer/deserializer.
216#[derive(Debug, Error)]
217pub enum BinarySerdeBufSafeError {
218    /// a deserialization error occured while trying to deserialize the bytes that were read from the buffer.
219    #[error("deserialization error")]
220    DeserializeError(
221        #[from]
222        #[source]
223        DeserializeError,
224    ),
225
226    /// the index is out of the bounds of the buffer
227    #[error("index {index} is out of bounds of buffer of len {buf_len}")]
228    OutOfBounds { index: usize, buf_len: usize },
229}
230/// binary serializes the given value using the given endianness into the given vector.
231#[cfg(feature = "std")]
232pub fn binary_serialize_into_vec<T: BinarySerde>(
233    value: &T,
234    endianness: Endianness,
235    vec: &mut Vec<u8>,
236) {
237    vec.reserve(T::SERIALIZED_SIZE);
238    value.binary_serialize(
239        unsafe {
240            core::slice::from_raw_parts_mut(vec.as_mut_ptr().add(vec.len()), T::SERIALIZED_SIZE)
241        },
242        endianness,
243    );
244    unsafe { vec.set_len(vec.len() + T::SERIALIZED_SIZE) }
245}
246
247/// a serializer which serializes value into a vector of bytes.
248#[cfg(feature = "std")]
249#[derive(Clone)]
250pub struct BinarySerializerToVec {
251    buf: Vec<u8>,
252    endianness: Endianness,
253}
254#[cfg(feature = "std")]
255impl BinarySerializerToVec {
256    /// creates a new serializer with an empty buffer and with the given endianness.
257    pub fn new(endianness: Endianness) -> Self {
258        Self {
259            buf: Vec::new(),
260            endianness,
261        }
262    }
263
264    /// creates a new serializer with the given initial buffer and endianness.
265    pub fn new_with_buffer(initial_buffer: Vec<u8>, endianness: Endianness) -> Self {
266        Self {
267            buf: initial_buffer,
268            endianness,
269        }
270    }
271
272    /// serializes the given value into the buffer.
273    pub fn serialize<T: BinarySerde>(&mut self, value: &T) {
274        binary_serialize_into_vec(value, self.endianness, &mut self.buf)
275    }
276
277    /// returns a reference to the serialized data in the buffer.
278    pub fn data(&self) -> &[u8] {
279        &self.buf
280    }
281
282    /// returns a refernece to the underlying buffer of the serializer.
283    pub fn buffer(&self) -> &Vec<u8> {
284        &self.buf
285    }
286
287    /// returns a mutable refernece to the underlying buffer of the serializer.
288    pub fn buffer_mut(&mut self) -> &mut Vec<u8> {
289        &mut self.buf
290    }
291
292    /// consumes this serializer and returns its internal buffer.
293    pub fn into_buffer(self) -> Vec<u8> {
294        self.buf
295    }
296
297    /// sets the endianness of this serializer
298    pub fn set_endianness(&mut self, new_endianness: Endianness) {
299        self.endianness = new_endianness
300    }
301
302    /// returns the endianness of this serializer.
303    pub fn endianness(&self) -> Endianness {
304        self.endianness
305    }
306}
307
308/// a serializer which serializes value into a data stream.
309#[cfg(feature = "std")]
310#[derive(Clone)]
311pub struct BinarySerializerToStream<W: std::io::Write> {
312    stream: W,
313    endianness: Endianness,
314}
315#[cfg(feature = "std")]
316impl<W: std::io::Write> BinarySerializerToStream<W> {
317    /// creates a new serializer which serializes into the given stream using the given endianness.
318    pub fn new(stream: W, endianness: Endianness) -> Self {
319        Self { stream, endianness }
320    }
321
322    /// serializes the given value into the stream.
323    pub fn serialize<T: BinarySerde>(&mut self, value: &T) -> std::io::Result<()> {
324        value.binary_serialize_into(&mut self.stream, self.endianness)
325    }
326
327    /// consumes this serializer and returns its internal stream.
328    pub fn into_stream(self) -> W {
329        self.stream
330    }
331
332    /// returns a refernece to the underlying stream of this serializer
333    pub fn stream(&self) -> &W {
334        &self.stream
335    }
336
337    /// returns a mutable refernece to the underlying stream of this serializer
338    pub fn stream_mut(&mut self) -> &mut W {
339        &mut self.stream
340    }
341
342    /// sets the endianness of this serializer
343    pub fn set_endianness(&mut self, new_endianness: Endianness) {
344        self.endianness = new_endianness
345    }
346
347    /// returns the endianness of this serializer.
348    pub fn endianness(&self) -> Endianness {
349        self.endianness
350    }
351}
352
353/// a deserializer which deserializes values from a buffer.
354#[derive(Clone)]
355pub struct BinaryDeserializerFromBuf<'a> {
356    buf: &'a [u8],
357    endianness: Endianness,
358    position: usize,
359}
360impl<'a> BinaryDeserializerFromBuf<'a> {
361    /// creates a new deserializer which deserializes values from the given buffer using the given endianness.
362    pub fn new(buf: &'a [u8], endianness: Endianness) -> Self {
363        Self {
364            buf,
365            endianness,
366            position: 0,
367        }
368    }
369
370    /// deserializes a value of type `T` from the current position in the buffer, and advances the position accordingly.
371    ///
372    /// # Panics
373    ///
374    /// this function panics if the deserialization exceeds the bounds of the buffer.
375    pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, DeserializeError> {
376        let result = T::binary_deserialize(
377            &self.buf[self.position..][..T::SERIALIZED_SIZE],
378            self.endianness,
379        )?;
380        self.position += T::SERIALIZED_SIZE;
381        Ok(result)
382    }
383
384    /// returns the current position of this deserializer in the buffer.
385    pub fn position(&self) -> usize {
386        self.position
387    }
388
389    /// sets the position of this deserializer in the buffer.
390    pub fn set_position(&mut self, new_position: usize) {
391        self.position = new_position;
392    }
393
394    /// moves this deserializer's position forwards according to the given amount.
395    pub fn move_forwards(&mut self, amount: usize) {
396        self.position += amount;
397    }
398
399    /// moves this deserializer's position backwards according to the given amount.
400    pub fn move_backwards(&mut self, amount: usize) {
401        self.position -= amount;
402    }
403
404    /// sets the endianness of this deserializer
405    pub fn set_endianness(&mut self, new_endianness: Endianness) {
406        self.endianness = new_endianness
407    }
408
409    /// returns the endianness of this deserializer.
410    pub fn endianness(&self) -> Endianness {
411        self.endianness
412    }
413
414    /// returns a reference to the underlying buffer of this deserializer
415    pub fn buf(&self) -> &'a [u8] {
416        self.buf
417    }
418}
419
420/// a binary serializer and deserializes which serializes and deserializes values to or from a buffer.
421pub struct BinarySerdeBuf<'a> {
422    buf: &'a mut [u8],
423    endianness: Endianness,
424    position: usize,
425}
426impl<'a> BinarySerdeBuf<'a> {
427    /// creates a new binary serializer/deserializer which serializes/deserializer values to/from the given buffer using
428    /// the given endianness.
429    pub fn new(buf: &'a mut [u8], endianness: Endianness) -> Self {
430        Self {
431            buf,
432            endianness,
433            position: 0,
434        }
435    }
436
437    /// serializes a value of type `T` into the current position in the buffer, and advances the position accordingly.
438    ///
439    /// # Panics
440    ///
441    /// this function panics if the serialization exceeds the bounds of the buffer.
442    pub fn serialize<T: BinarySerde>(&mut self, value: &T) {
443        value.binary_serialize(
444            &mut self.buf[self.position..][..T::SERIALIZED_SIZE],
445            self.endianness,
446        );
447        self.position += T::SERIALIZED_SIZE;
448    }
449
450    /// consumes and returns the next `amount` bytes from the current position in the buffer, and advances the position accordingly.
451    ///
452    /// # Panics
453    ///
454    /// this function panics if the requested amount of bytes exceeds the bounds of the buffer.
455    pub fn consume_bytes(&mut self, amount: usize) -> &[u8] {
456        let result = &self.buf[self.position..][..amount];
457        self.position += amount;
458        result
459    }
460
461    /// deserializes a value of type `T` from the current position in the buffer, and advances the position accordingly.
462    ///
463    /// # Panics
464    ///
465    /// this function panics if the deserialization exceeds the bounds of the buffer.
466    pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, DeserializeError> {
467        let result = T::binary_deserialize(
468            &self.buf[self.position..][..T::SERIALIZED_SIZE],
469            self.endianness,
470        )?;
471        self.position += T::SERIALIZED_SIZE;
472        Ok(result)
473    }
474
475    /// returns the current position of this deserializer in the buffer.
476    pub fn position(&self) -> usize {
477        self.position
478    }
479
480    /// sets the position of this deserializer in the buffer.
481    pub fn set_position(&mut self, new_position: usize) {
482        self.position = new_position;
483    }
484
485    /// moves this deserializer's position forwards according to the given amount.
486    pub fn move_forwards(&mut self, amount: usize) {
487        self.position += amount;
488    }
489
490    /// moves this deserializer's position backwards according to the given amount.
491    pub fn move_backwards(&mut self, amount: usize) {
492        self.position -= amount;
493    }
494
495    /// sets the endianness of this serializer/deserializer
496    pub fn set_endianness(&mut self, new_endianness: Endianness) {
497        self.endianness = new_endianness
498    }
499
500    /// returns the endianness of this serializer/deserializer.
501    pub fn endianness(&self) -> Endianness {
502        self.endianness
503    }
504
505    /// returns a reference to the underlying buffer of this serializer/deserializer.
506    pub fn buf(&mut self) -> &mut [u8] {
507        self.buf
508    }
509}
510
511/// a binary serializer/deserializer which serializes/deserializer values to a buffer and performs bounds checks on the buffer
512/// when serializing/deserializing to avoid panics.
513pub struct BinarySerdeBufSafe<'a> {
514    buf: &'a mut [u8],
515    endianness: Endianness,
516    position: usize,
517}
518impl<'a> BinarySerdeBufSafe<'a> {
519    /// creates a new binary serializer/deserializer which serializes/deserializer values to/from the given buffer using
520    /// the given endianness.
521    pub fn new(buf: &'a mut [u8], endianness: Endianness) -> Self {
522        Self {
523            buf,
524            endianness,
525            position: 0,
526        }
527    }
528
529    /// checks that the given index is in range of the buffer, and if it is not, returns an error.
530    fn check_index(&self, index: usize) -> Result<(), BinarySerdeBufSafeError> {
531        if index < self.buf.len() {
532            Ok(())
533        } else {
534            Err(BinarySerdeBufSafeError::OutOfBounds {
535                index,
536                buf_len: self.buf.len(),
537            })
538        }
539    }
540
541    /// serializes a value of type `T` into the current position in the buffer, and advances the position accordingly.
542    pub fn serialize<T: BinarySerde>(&mut self, value: &T) -> Result<(), BinarySerdeBufSafeError> {
543        // make sure that the start index is in range
544        self.check_index(self.position)?;
545
546        // if the end index is not the same as the start index, make sure that it is also in range
547        if T::SERIALIZED_SIZE > 1 {
548            self.check_index(self.position + T::SERIALIZED_SIZE - 1)?;
549        }
550
551        value.binary_serialize(
552            &mut self.buf[self.position..][..T::SERIALIZED_SIZE],
553            self.endianness,
554        );
555        self.position += T::SERIALIZED_SIZE;
556
557        Ok(())
558    }
559
560    /// consumes and returns the next `amount` bytes from the current position in the buffer, and advances the position accordingly.
561    pub fn consume_bytes(&mut self, amount: usize) -> Result<&[u8], BinarySerdeBufSafeError> {
562        // make sure that the start index is in range
563        self.check_index(self.position)?;
564
565        // if the end index is not the same as the start index, make sure that it is also in range
566        if amount > 1 {
567            self.check_index(self.position + amount - 1)?;
568        }
569
570        let result = &self.buf[self.position..][..amount];
571        self.position += amount;
572
573        Ok(result)
574    }
575
576    /// deserializes a value of type `T` from the current position in the buffer, and advances the position accordingly.
577    pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, BinarySerdeBufSafeError> {
578        // make sure that the start index is in range
579        self.check_index(self.position)?;
580
581        // if the end index is not the same as the start index, make sure that it is also in range
582        if T::SERIALIZED_SIZE > 1 {
583            self.check_index(self.position + T::SERIALIZED_SIZE - 1)?;
584        }
585
586        let result = T::binary_deserialize(
587            &self.buf[self.position..][..T::SERIALIZED_SIZE],
588            self.endianness,
589        )?;
590        self.position += T::SERIALIZED_SIZE;
591        Ok(result)
592    }
593
594    /// returns the current position of this deserializer in the buffer.
595    pub fn position(&self) -> usize {
596        self.position
597    }
598
599    /// sets the position of this deserializer in the buffer.
600    pub fn set_position(&mut self, new_position: usize) {
601        self.position = new_position;
602    }
603
604    /// moves this deserializer's position forwards according to the given amount.
605    pub fn move_forwards(&mut self, amount: usize) {
606        self.position += amount;
607    }
608
609    /// moves this deserializer's position backwards according to the given amount.
610    pub fn move_backwards(&mut self, amount: usize) {
611        self.position -= amount;
612    }
613
614    /// sets the endianness of this serializer/deserializer
615    pub fn set_endianness(&mut self, new_endianness: Endianness) {
616        self.endianness = new_endianness
617    }
618
619    /// returns the endianness of this serializer/deserializer.
620    pub fn endianness(&self) -> Endianness {
621        self.endianness
622    }
623
624    /// returns a reference to the underlying buffer of this serializer/deserializer.
625    pub fn buf(&mut self) -> &mut [u8] {
626        self.buf
627    }
628}
629
630/// a deserializer which deserializes values from a buffer and performs bounds checks on the buffer when deserializing
631/// to avoid panics.
632#[derive(Clone)]
633pub struct BinaryDeserializerFromBufSafe<'a> {
634    buf: &'a [u8],
635    endianness: Endianness,
636    position: usize,
637}
638impl<'a> BinaryDeserializerFromBufSafe<'a> {
639    /// creates a new deserializer which deserializes values from the given buffer using the given endianness.
640    pub fn new(buf: &'a [u8], endianness: Endianness) -> Self {
641        Self {
642            buf,
643            endianness,
644            position: 0,
645        }
646    }
647
648    /// checks that the given index is in range of the buffer, and if it is not, returns an error.
649    fn check_index(&self, index: usize) -> Result<(), BinarySerdeBufSafeError> {
650        if index < self.buf.len() {
651            Ok(())
652        } else {
653            Err(BinarySerdeBufSafeError::OutOfBounds {
654                index,
655                buf_len: self.buf.len(),
656            })
657        }
658    }
659
660    /// deserializes a value of type `T` from the current position in the buffer, and advances the position accordingly.
661    pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, BinarySerdeBufSafeError> {
662        // make sure that the start index is in range
663        self.check_index(self.position)?;
664
665        // if the end index is not the same as the start index, make sure that it is also in range
666        if T::SERIALIZED_SIZE > 1 {
667            self.check_index(self.position + T::SERIALIZED_SIZE - 1)?;
668        }
669
670        let result = T::binary_deserialize(
671            &self.buf[self.position..][..T::SERIALIZED_SIZE],
672            self.endianness,
673        )?;
674        self.position += T::SERIALIZED_SIZE;
675        Ok(result)
676    }
677
678    /// returns the current position of this deserializer in the buffer.
679    pub fn position(&self) -> usize {
680        self.position
681    }
682
683    /// sets the position of this deserializer in the buffer.
684    pub fn set_position(&mut self, new_position: usize) {
685        self.position = new_position;
686    }
687
688    /// moves this deserializer's position forwards according to the given amount.
689    pub fn move_forwards(&mut self, amount: usize) {
690        self.position += amount;
691    }
692
693    /// moves this deserializer's position backwards according to the given amount.
694    pub fn move_backwards(&mut self, amount: usize) {
695        self.position -= amount;
696    }
697
698    /// sets the endianness of this deserializer
699    pub fn set_endianness(&mut self, new_endianness: Endianness) {
700        self.endianness = new_endianness
701    }
702
703    /// returns the endianness of this deserializer.
704    pub fn endianness(&self) -> Endianness {
705        self.endianness
706    }
707
708    /// returns a reference to the underlying buffer of this deserializer.
709    pub fn buf(&self) -> &'a [u8] {
710        self.buf
711    }
712}
713
714/// a deserializer which deserializes values from a data stream.
715#[cfg(feature = "std")]
716#[derive(Clone)]
717pub struct BinaryDeserializerFromStream<R: std::io::Read> {
718    stream: R,
719    endianness: Endianness,
720}
721#[cfg(feature = "std")]
722impl<R: std::io::Read> BinaryDeserializerFromStream<R> {
723    /// creates a new deserializer which deserializes values from the given data stream using the given endianness.
724    pub fn new(stream: R, endianness: Endianness) -> Self {
725        Self { stream, endianness }
726    }
727
728    /// deserializes a value of type `T` from the data stream.
729    pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, DeserializeFromError> {
730        T::binary_deserialize_from(&mut self.stream, self.endianness)
731    }
732
733    /// consumes this deserializer and returns its internal stream.
734    pub fn into_stream(self) -> R {
735        self.stream
736    }
737
738    /// returns a refernece to the underlying stream of this deserializer
739    pub fn stream(&self) -> &R {
740        &self.stream
741    }
742
743    /// returns a mutable refernece to the underlying stream of this deserializer
744    pub fn stream_mut(&mut self) -> &mut R {
745        &mut self.stream
746    }
747
748    /// sets the endianness of this deserializer
749    pub fn set_endianness(&mut self, new_endianness: Endianness) {
750        self.endianness = new_endianness
751    }
752
753    /// returns the endianness of this deserializer.
754    pub fn endianness(&self) -> Endianness {
755        self.endianness
756    }
757}
758
759/// extracts the bits at the given range from the given byte.
760fn get_bits_of_byte(byte: u8, start_bit_index: usize, bits_amount: usize) -> u8 {
761    let mask = if bits_amount == 8 {
762        u8::MAX
763    } else {
764        (1 << bits_amount) - 1
765    };
766    (byte >> start_bit_index) & mask
767}
768
769/// returns a bitmask which extracts the bits at the given range from a byte.
770fn get_bits_mask(start_bit_index: usize, bits_amount: usize) -> u8 {
771    if bits_amount == 8 {
772        u8::MAX
773    } else {
774        let unshifted = (1 << bits_amount) - 1;
775        unshifted << start_bit_index
776    }
777}
778
779/// a bit reader which allows reading a byte slice as a sequence of bits in an lsb first format.
780#[doc(hidden)]
781#[derive(Clone)]
782pub struct LsbBitReader<'a> {
783    bytes: &'a [u8],
784    bit_index_in_cur_byte: usize,
785    endianness: Endianness,
786    endianness_neutral_byte_index: usize,
787}
788impl<'a> LsbBitReader<'a> {
789    /// creates a new bit reader which reads from the given byte array using the given endianness.
790    pub fn new(bytes: &'a [u8], endianness: Endianness) -> Self {
791        Self {
792            bytes,
793            bit_index_in_cur_byte: 0,
794            endianness,
795            endianness_neutral_byte_index: 0,
796        }
797    }
798
799    /// returns the current byte index while taking into account the endianness.
800    pub fn cur_byte_index(&self) -> usize {
801        match self.endianness {
802            Endianness::Big => self.bytes.len() - 1 - self.endianness_neutral_byte_index,
803            Endianness::Little => self.endianness_neutral_byte_index,
804        }
805    }
806
807    /// returns the amount of bits left to read from the current byte. this is a value between 1-8 (including both ends).
808    pub fn bits_left_in_cur_byte(&self) -> usize {
809        8 - self.bit_index_in_cur_byte
810    }
811
812    /// reads the given amount of bits from this bit reader and advances the reader by the given amount.
813    /// the provided amount must be lower than or equal to the amount of bits left to read from the current byte, such
814    /// that the read doesn't require crossing a byte boundary.
815    pub fn read_bits(&mut self, bits_amount: usize) -> u8 {
816        assert!(bits_amount <= self.bits_left_in_cur_byte());
817        let cur_byte_index = self.cur_byte_index();
818        let result = get_bits_of_byte(
819            self.bytes[cur_byte_index],
820            self.bit_index_in_cur_byte,
821            bits_amount,
822        );
823
824        self.bit_index_in_cur_byte += bits_amount;
825        if self.bit_index_in_cur_byte == 8 {
826            self.endianness_neutral_byte_index += 1;
827            self.bit_index_in_cur_byte = 0;
828        }
829
830        result
831    }
832}
833
834/// a bit writer which allows writing bit sequences to a byte slice in an lsb first format.
835#[doc(hidden)]
836pub struct LsbBitWriter<'a> {
837    bytes: &'a mut [u8],
838    bit_index_in_cur_byte: usize,
839    endianness: Endianness,
840    endianness_neutral_byte_index: usize,
841}
842impl<'a> LsbBitWriter<'a> {
843    /// creates a new bit writer which writes to the given byte array using the given endianness, starting at the given bit offset.
844    pub fn new(bytes: &'a mut [u8], endianness: Endianness) -> Self {
845        Self {
846            bit_index_in_cur_byte: 0,
847            endianness,
848            endianness_neutral_byte_index: 0,
849            bytes,
850        }
851    }
852
853    /// returns the current byte index while taking into account the endianness.
854    pub fn cur_byte_index(&self) -> usize {
855        match self.endianness {
856            Endianness::Big => self.bytes.len() - 1 - self.endianness_neutral_byte_index,
857            Endianness::Little => self.endianness_neutral_byte_index,
858        }
859    }
860
861    /// returns the amount of bits left to write to the current byte. this is a value between 1-8 (including both ends).
862    pub fn bits_left_in_cur_byte(&self) -> usize {
863        8 - self.bit_index_in_cur_byte
864    }
865
866    /// writes the given amount of bits from the given bits and advances the bit writer by the given amount.
867    /// the provided amount must be lower than or equal to the amount of bits left to write from the current byte, such
868    /// that the write doesn't require crossing a byte boundary.
869    pub fn write_bits(&mut self, bits: u8, bits_amount: usize) {
870        let cur_byte_index = self.cur_byte_index();
871        let mask = get_bits_mask(self.bit_index_in_cur_byte, bits_amount);
872        self.bytes[cur_byte_index] =
873            (self.bytes[cur_byte_index] & !mask) | (bits << self.bit_index_in_cur_byte);
874
875        self.bit_index_in_cur_byte += bits_amount;
876        if self.bit_index_in_cur_byte == 8 {
877            self.endianness_neutral_byte_index += 1;
878            self.bit_index_in_cur_byte = 0;
879        }
880    }
881}
882
883/// copies the given amount of bits from the `from` reader to the `to` writer.
884#[doc(hidden)]
885pub fn _copy_bits<'a, 'b>(
886    from: &mut LsbBitReader<'a>,
887    to: &mut LsbBitWriter<'b>,
888    bits_amount: usize,
889) {
890    let mut bits_left = bits_amount;
891    while bits_left > 0 {
892        // calculate the amount of bits to copy in the current iteration such that we don't cross byte boundaries both in the
893        // reader and writer, and also take into account the amount of bits left to copy.
894        let cur_amount = core::cmp::min(
895            core::cmp::min(from.bits_left_in_cur_byte(), to.bits_left_in_cur_byte()),
896            bits_left,
897        );
898
899        to.write_bits(from.read_bits(cur_amount), cur_amount);
900        bits_left -= cur_amount;
901    }
902}
903
904/// a struct used for adding padding in the middle of your serializable structs.
905/// when serializing, it will write the `PADDING_VALUE` to the buffer `PADDING_LENGTH` times.
906/// deserializing, it will do nothing.
907#[derive(Debug, Clone, Copy, Hash)]
908pub struct BinarySerdePadding<const PADDING_LENGTH: usize, const PADDING_VALUE: u8>;
909impl<const PADDING_LENGTH: usize, const PADDING_VALUE: u8> BinarySerde
910    for BinarySerdePadding<PADDING_LENGTH, PADDING_VALUE>
911{
912    const SERIALIZED_SIZE: usize = PADDING_LENGTH;
913
914    type RecursiveArray = recursive_array_type_of_size!(u8, PADDING_LENGTH);
915
916    fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
917        buf[..PADDING_LENGTH].fill(PADDING_VALUE);
918    }
919
920    fn binary_deserialize(_buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
921        Ok(Self)
922    }
923}
924
925/// implements the [`BinarySerde`] trait for a type generated using the `bitflags!` macro from the `bitflags` crate.
926#[macro_export]
927macro_rules! impl_binary_serde_for_bitflags_ty {
928    {$bitflags_ty: ty} => {
929        impl ::binary_serde::BinarySerde for $bitflags_ty
930        where
931            <$bitflags_ty as ::bitflags::Flags>::Bits: ::binary_serde::BinarySerde,
932        {
933            const SERIALIZED_SIZE: usize =
934                <<$bitflags_ty as ::bitflags::Flags>::Bits as ::binary_serde::BinarySerde>::SERIALIZED_SIZE;
935
936            type RecursiveArray =
937                <<$bitflags_ty as ::bitflags::Flags>::Bits as ::binary_serde::BinarySerde>::RecursiveArray;
938
939            fn binary_serialize(&self, buf: &mut [u8], endianness: ::binary_serde::Endianness) {
940                let bits = ::bitflags::Flags::bits(self);
941                ::binary_serde::BinarySerde::binary_serialize(&bits, buf, endianness)
942            }
943
944            fn binary_deserialize(
945                buf: &[u8],
946                endianness: ::binary_serde::Endianness,
947            ) -> Result<Self, ::binary_serde::DeserializeError> {
948                let bits = ::binary_serde::BinarySerde::binary_deserialize(buf, endianness)?;
949                Ok(::bitflags::Flags::from_bits_retain(bits))
950            }
951
952            fn binary_serialize_to_array(
953                &self,
954                endianness: ::binary_serde::Endianness,
955            ) -> Self::RecursiveArray {
956                let bits = ::bitflags::Flags::bits(self);
957                ::binary_serde::BinarySerde::binary_serialize_to_array(&bits, endianness)
958            }
959        }
960    };
961}
962
963impl BinarySerde for u8 {
964    const SERIALIZED_SIZE: usize = 1;
965
966    type RecursiveArray = RecursiveArraySingleItem<u8>;
967
968    fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
969        buf[0] = *self;
970    }
971
972    fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
973        RecursiveArraySingleItem::new(*self)
974    }
975
976    #[cfg(feature = "std")]
977    fn binary_serialize_into<W: std::io::Write>(
978        &self,
979        stream: &mut W,
980        _endianness: Endianness,
981    ) -> std::io::Result<()> {
982        stream.write_all(&[*self])
983    }
984
985    fn binary_deserialize(buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
986        Ok(buf[0])
987    }
988
989    #[cfg(feature = "std")]
990    fn binary_deserialize_from<R: std::io::Read>(
991        stream: &mut R,
992        _endianness: Endianness,
993    ) -> Result<Self, DeserializeFromError> {
994        let mut result: core::mem::MaybeUninit<Self> = core::mem::MaybeUninit::uninit();
995        stream.read_exact(unsafe { core::slice::from_raw_parts_mut(result.as_mut_ptr(), 1) })?;
996        Ok(unsafe { result.assume_init() })
997    }
998}
999
1000impl BinarySerde for i8 {
1001    const SERIALIZED_SIZE: usize = 1;
1002
1003    type RecursiveArray = RecursiveArraySingleItem<u8>;
1004
1005    fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
1006        buf[0] = *self as u8;
1007    }
1008
1009    fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
1010        RecursiveArraySingleItem::new(*self as u8)
1011    }
1012
1013    #[cfg(feature = "std")]
1014    fn binary_serialize_into<W: std::io::Write>(
1015        &self,
1016        stream: &mut W,
1017        _endianness: Endianness,
1018    ) -> std::io::Result<()> {
1019        stream.write_all(&[*self as u8])
1020    }
1021
1022    fn binary_deserialize(buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
1023        Ok(buf[0] as i8)
1024    }
1025
1026    #[cfg(feature = "std")]
1027    fn binary_deserialize_from<R: std::io::Read>(
1028        stream: &mut R,
1029        _endianness: Endianness,
1030    ) -> Result<Self, DeserializeFromError> {
1031        let mut result: core::mem::MaybeUninit<u8> = core::mem::MaybeUninit::uninit();
1032        stream.read_exact(unsafe { core::slice::from_raw_parts_mut(result.as_mut_ptr(), 1) })?;
1033        let byte = unsafe { result.assume_init() };
1034        Ok(byte as i8)
1035    }
1036}
1037
1038impl BinarySerde for bool {
1039    const SERIALIZED_SIZE: usize = 1;
1040
1041    type RecursiveArray = RecursiveArraySingleItem<u8>;
1042
1043    fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
1044        buf[0] = *self as u8;
1045    }
1046
1047    fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
1048        RecursiveArraySingleItem::new(*self as u8)
1049    }
1050
1051    #[cfg(feature = "std")]
1052    fn binary_serialize_into<W: std::io::Write>(
1053        &self,
1054        stream: &mut W,
1055        _endianness: Endianness,
1056    ) -> std::io::Result<()> {
1057        stream.write_all(&[*self as u8])
1058    }
1059
1060    fn binary_deserialize(buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
1061        Ok(buf[0] != 0)
1062    }
1063
1064    #[cfg(feature = "std")]
1065    fn binary_deserialize_from<R: std::io::Read>(
1066        stream: &mut R,
1067        _endianness: Endianness,
1068    ) -> Result<Self, DeserializeFromError> {
1069        let mut result: core::mem::MaybeUninit<u8> = core::mem::MaybeUninit::uninit();
1070        stream.read_exact(unsafe { core::slice::from_raw_parts_mut(result.as_mut_ptr(), 1) })?;
1071        let byte = unsafe { result.assume_init() };
1072        Ok(byte != 0)
1073    }
1074}
1075
1076impl<T> BinarySerde for PhantomData<T> {
1077    const SERIALIZED_SIZE: usize = 0;
1078
1079    type RecursiveArray = EmptyRecursiveArray;
1080
1081    fn binary_serialize(&self, _buf: &mut [u8], _endianness: Endianness) {}
1082
1083    fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
1084        EmptyRecursiveArray
1085    }
1086
1087    #[cfg(feature = "std")]
1088    fn binary_serialize_into<W: std::io::Write>(
1089        &self,
1090        _stream: &mut W,
1091        _endianness: Endianness,
1092    ) -> std::io::Result<()> {
1093        Ok(())
1094    }
1095
1096    fn binary_deserialize(_buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
1097        Ok(Self)
1098    }
1099
1100    #[cfg(feature = "std")]
1101    fn binary_deserialize_from<R: std::io::Read>(
1102        _stream: &mut R,
1103        _endianness: Endianness,
1104    ) -> Result<Self, DeserializeFromError> {
1105        Ok(Self)
1106    }
1107}
1108
1109impl BinarySerde for () {
1110    const SERIALIZED_SIZE: usize = 0;
1111
1112    type RecursiveArray = EmptyRecursiveArray;
1113
1114    fn binary_serialize(&self, _buf: &mut [u8], _endianness: Endianness) {}
1115
1116    fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
1117        EmptyRecursiveArray
1118    }
1119
1120    #[cfg(feature = "std")]
1121    fn binary_serialize_into<W: std::io::Write>(
1122        &self,
1123        _stream: &mut W,
1124        _endianness: Endianness,
1125    ) -> std::io::Result<()> {
1126        Ok(())
1127    }
1128
1129    fn binary_deserialize(_buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
1130        Ok(())
1131    }
1132
1133    #[cfg(feature = "std")]
1134    fn binary_deserialize_from<R: std::io::Read>(
1135        _stream: &mut R,
1136        _endianness: Endianness,
1137    ) -> Result<Self, DeserializeFromError> {
1138        Ok(())
1139    }
1140}
1141
1142impl<const N: usize, T: BinarySerde> BinarySerde for [T; N] {
1143    const SERIALIZED_SIZE: usize = T::SERIALIZED_SIZE * N;
1144
1145    type RecursiveArray = RecursiveArrayMultiplier<N, u8, T::RecursiveArray>;
1146
1147    fn binary_serialize(&self, buf: &mut [u8], endianness: Endianness) {
1148        /// an iterator which zips 2 iterators and makes sure that they are of the same length, and panics if they are not.
1149        struct ZipExact<A: Iterator, B: Iterator> {
1150            a: A,
1151            b: B,
1152        }
1153        impl<A: Iterator, B: Iterator> Iterator for ZipExact<A, B> {
1154            type Item = (A::Item, B::Item);
1155
1156            fn next(&mut self) -> Option<Self::Item> {
1157                match (self.a.next(), self.b.next()) {
1158                    (Some(a), Some(b)) => Some((a, b)),
1159                    (None, None) => None,
1160                    _ => panic!("zipped iterators are of different lengths"),
1161                }
1162            }
1163        }
1164        /// zip 2 iterators into an iterator which yields a single item at a time from both iterators, and panics if the iterators
1165        /// are not of the same length.
1166        fn zip_exact<A: Iterator, B: Iterator>(a: A, b: B) -> ZipExact<A, B> {
1167            ZipExact { a, b }
1168        }
1169
1170        for (item, item_buf) in zip_exact(self.iter(), buf.chunks_mut(T::SERIALIZED_SIZE)) {
1171            item.binary_serialize(item_buf, endianness)
1172        }
1173    }
1174
1175    fn binary_deserialize(buf: &[u8], endianness: Endianness) -> Result<Self, DeserializeError> {
1176        array_init::try_array_init(|i| {
1177            T::binary_deserialize(
1178                &buf[i * T::SERIALIZED_SIZE..][..T::SERIALIZED_SIZE],
1179                endianness,
1180            )
1181        })
1182    }
1183}
1184
1185macro_rules! impl_for_primitive_types {
1186    {$($type: ty),+} => {
1187        $(
1188            impl BinarySerde for $type {
1189                const SERIALIZED_SIZE: usize = core::mem::size_of::<Self>();
1190                type RecursiveArray = recursive_array_type_of_size!(u8, core::mem::size_of::<Self>());
1191
1192                fn binary_serialize(&self, buf: &mut [u8], endianness: Endianness) {
1193                    let bytes = match endianness {
1194                        Endianness::Big => self.to_be_bytes(),
1195                        Endianness::Little => self.to_le_bytes(),
1196                    };
1197                    buf.copy_from_slice(bytes.as_slice());
1198                }
1199                fn binary_deserialize(buf: &[u8], endianness: Endianness) -> Result<Self, DeserializeError> {
1200                    let array = buf.try_into().unwrap();
1201                    Ok(match endianness {
1202                        Endianness::Big => Self::from_be_bytes(array),
1203                        Endianness::Little => Self::from_le_bytes(array),
1204                    })
1205                }
1206            }
1207        )+
1208    };
1209}
1210
1211impl_for_primitive_types! {u16,u32,u64,u128,i16,i32,i64,i128,f32,f64}