#![cfg_attr(not(feature = "std"), no_std)]
use core::marker::PhantomData;
pub use binary_serde_macros::{binary_serde_bitfield, BinarySerde};
use recursive_array::{
recursive_array_type_of_size, EmptyRecursiveArray, RecursiveArray, RecursiveArrayMultiplier,
RecursiveArraySingleItem,
};
pub use recursive_array;
use thiserror_no_std::Error;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Endianness {
Big,
Little,
}
impl Endianness {
#[cfg(target_endian = "little")]
pub const NATIVE: Self = Endianness::Little;
#[cfg(target_endian = "big")]
pub const NATIVE: Self = Endianness::Big;
}
pub enum BitfieldBitOrder {
MsbFirst,
LsbFirst,
}
pub trait BinarySerde: Sized {
const SERIALIZED_SIZE: usize;
type RecursiveArray: RecursiveArray<u8>;
fn binary_serialize(&self, buf: &mut [u8], endianness: Endianness);
fn binary_serialize_to_array(&self, endianness: Endianness) -> Self::RecursiveArray {
let mut array: core::mem::MaybeUninit<Self::RecursiveArray> =
core::mem::MaybeUninit::uninit();
self.binary_serialize(
unsafe {
core::slice::from_raw_parts_mut(
array.as_mut_ptr().cast::<u8>(),
Self::SERIALIZED_SIZE,
)
},
endianness,
);
unsafe { array.assume_init() }
}
#[cfg(feature = "std")]
fn binary_serialize_into<W: std::io::Write>(
&self,
stream: &mut W,
endianness: Endianness,
) -> std::io::Result<()> {
let serialized = self.binary_serialize_to_array(endianness);
stream.write_all(serialized.as_slice())?;
Ok(())
}
fn binary_deserialize(buf: &[u8], endianness: Endianness) -> Result<Self, DeserializeError>;
#[cfg(feature = "std")]
fn binary_deserialize_from<R: std::io::Read>(
stream: &mut R,
endianness: Endianness,
) -> Result<Self, DeserializeFromError> {
let mut uninit_array: core::mem::MaybeUninit<Self::RecursiveArray> =
core::mem::MaybeUninit::uninit();
stream.read_exact(unsafe {
core::slice::from_raw_parts_mut(
uninit_array.as_mut_ptr().cast::<u8>(),
Self::SERIALIZED_SIZE,
)
})?;
let array = unsafe { uninit_array.assume_init() };
Ok(Self::binary_deserialize(array.as_slice(), endianness)?)
}
}
#[derive(Debug, Error)]
pub enum DeserializeError {
#[error("invalid value for enum {enum_name}")]
InvalidEnumValue { enum_name: &'static str },
}
#[cfg(feature = "std")]
#[derive(Debug, Error)]
pub enum DeserializeFromError {
#[error("io error while reading from stream")]
IoError(
#[from]
#[source]
std::io::Error,
),
#[error("deserialization error")]
DeserializeError(
#[from]
#[source]
DeserializeError,
),
}
#[derive(Debug, Error)]
pub enum BinarySerdeBufSafeError {
#[error("deserialization error")]
DeserializeError(
#[from]
#[source]
DeserializeError,
),
#[error("index {index} is out of bounds of buffer of len {buf_len}")]
OutOfBounds { index: usize, buf_len: usize },
}
#[cfg(feature = "std")]
pub fn binary_serialize_into_vec<T: BinarySerde>(
value: &T,
endianness: Endianness,
vec: &mut Vec<u8>,
) {
vec.reserve(T::SERIALIZED_SIZE);
value.binary_serialize(
unsafe {
core::slice::from_raw_parts_mut(vec.as_mut_ptr().add(vec.len()), T::SERIALIZED_SIZE)
},
endianness,
);
unsafe { vec.set_len(vec.len() + T::SERIALIZED_SIZE) }
}
#[cfg(feature = "std")]
#[derive(Clone)]
pub struct BinarySerializerToVec {
buf: Vec<u8>,
endianness: Endianness,
}
#[cfg(feature = "std")]
impl BinarySerializerToVec {
pub fn new(endianness: Endianness) -> Self {
Self {
buf: Vec::new(),
endianness,
}
}
pub fn new_with_buffer(initial_buffer: Vec<u8>, endianness: Endianness) -> Self {
Self {
buf: initial_buffer,
endianness,
}
}
pub fn serialize<T: BinarySerde>(&mut self, value: &T) {
binary_serialize_into_vec(value, self.endianness, &mut self.buf)
}
pub fn data(&self) -> &[u8] {
&self.buf
}
pub fn buffer(&self) -> &Vec<u8> {
&self.buf
}
pub fn buffer_mut(&mut self) -> &mut Vec<u8> {
&mut self.buf
}
pub fn into_buffer(self) -> Vec<u8> {
self.buf
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
}
#[cfg(feature = "std")]
#[derive(Clone)]
pub struct BinarySerializerToStream<W: std::io::Write> {
stream: W,
endianness: Endianness,
}
#[cfg(feature = "std")]
impl<W: std::io::Write> BinarySerializerToStream<W> {
pub fn new(stream: W, endianness: Endianness) -> Self {
Self { stream, endianness }
}
pub fn serialize<T: BinarySerde>(&mut self, value: &T) -> std::io::Result<()> {
value.binary_serialize_into(&mut self.stream, self.endianness)
}
pub fn into_stream(self) -> W {
self.stream
}
pub fn stream(&self) -> &W {
&self.stream
}
pub fn stream_mut(&mut self) -> &mut W {
&mut self.stream
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
}
#[derive(Clone)]
pub struct BinaryDeserializerFromBuf<'a> {
buf: &'a [u8],
endianness: Endianness,
position: usize,
}
impl<'a> BinaryDeserializerFromBuf<'a> {
pub fn new(buf: &'a [u8], endianness: Endianness) -> Self {
Self {
buf,
endianness,
position: 0,
}
}
pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, DeserializeError> {
let result = T::binary_deserialize(
&self.buf[self.position..][..T::SERIALIZED_SIZE],
self.endianness,
)?;
self.position += T::SERIALIZED_SIZE;
Ok(result)
}
pub fn position(&self) -> usize {
self.position
}
pub fn set_position(&mut self, new_position: usize) {
self.position = new_position;
}
pub fn move_forwards(&mut self, amount: usize) {
self.position += amount;
}
pub fn move_backwards(&mut self, amount: usize) {
self.position -= amount;
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
pub fn buf(&self) -> &'a [u8] {
self.buf
}
}
pub struct BinarySerdeBuf<'a> {
buf: &'a mut [u8],
endianness: Endianness,
position: usize,
}
impl<'a> BinarySerdeBuf<'a> {
pub fn new(buf: &'a mut [u8], endianness: Endianness) -> Self {
Self {
buf,
endianness,
position: 0,
}
}
pub fn serialize<T: BinarySerde>(&mut self, value: &T) {
value.binary_serialize(
&mut self.buf[self.position..][..T::SERIALIZED_SIZE],
self.endianness,
);
self.position += T::SERIALIZED_SIZE;
}
pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, DeserializeError> {
let result = T::binary_deserialize(
&self.buf[self.position..][..T::SERIALIZED_SIZE],
self.endianness,
)?;
self.position += T::SERIALIZED_SIZE;
Ok(result)
}
pub fn position(&self) -> usize {
self.position
}
pub fn set_position(&mut self, new_position: usize) {
self.position = new_position;
}
pub fn move_forwards(&mut self, amount: usize) {
self.position += amount;
}
pub fn move_backwards(&mut self, amount: usize) {
self.position -= amount;
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
pub fn buf(&mut self) -> &mut [u8] {
self.buf
}
}
pub struct BinarySerdeBufSafe<'a> {
buf: &'a mut [u8],
endianness: Endianness,
position: usize,
}
impl<'a> BinarySerdeBufSafe<'a> {
pub fn new(buf: &'a mut [u8], endianness: Endianness) -> Self {
Self {
buf,
endianness,
position: 0,
}
}
fn check_index(&self, index: usize) -> Result<(), BinarySerdeBufSafeError> {
if index < self.buf.len() {
Ok(())
} else {
Err(BinarySerdeBufSafeError::OutOfBounds {
index,
buf_len: self.buf.len(),
})
}
}
pub fn serialize<T: BinarySerde>(&mut self, value: &T) -> Result<(), BinarySerdeBufSafeError> {
self.check_index(self.position)?;
if T::SERIALIZED_SIZE > 1 {
self.check_index(self.position + T::SERIALIZED_SIZE - 1)?;
}
value.binary_serialize(
&mut self.buf[self.position..][..T::SERIALIZED_SIZE],
self.endianness,
);
self.position += T::SERIALIZED_SIZE;
Ok(())
}
pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, BinarySerdeBufSafeError> {
self.check_index(self.position)?;
if T::SERIALIZED_SIZE > 1 {
self.check_index(self.position + T::SERIALIZED_SIZE - 1)?;
}
let result = T::binary_deserialize(
&self.buf[self.position..][..T::SERIALIZED_SIZE],
self.endianness,
)?;
self.position += T::SERIALIZED_SIZE;
Ok(result)
}
pub fn position(&self) -> usize {
self.position
}
pub fn set_position(&mut self, new_position: usize) {
self.position = new_position;
}
pub fn move_forwards(&mut self, amount: usize) {
self.position += amount;
}
pub fn move_backwards(&mut self, amount: usize) {
self.position -= amount;
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
pub fn buf(&mut self) -> &mut [u8] {
self.buf
}
}
#[derive(Clone)]
pub struct BinaryDeserializerFromBufSafe<'a> {
buf: &'a [u8],
endianness: Endianness,
position: usize,
}
impl<'a> BinaryDeserializerFromBufSafe<'a> {
pub fn new(buf: &'a [u8], endianness: Endianness) -> Self {
Self {
buf,
endianness,
position: 0,
}
}
fn check_index(&self, index: usize) -> Result<(), BinarySerdeBufSafeError> {
if index < self.buf.len() {
Ok(())
} else {
Err(BinarySerdeBufSafeError::OutOfBounds {
index,
buf_len: self.buf.len(),
})
}
}
pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, BinarySerdeBufSafeError> {
self.check_index(self.position)?;
if T::SERIALIZED_SIZE > 1 {
self.check_index(self.position + T::SERIALIZED_SIZE - 1)?;
}
let result = T::binary_deserialize(
&self.buf[self.position..][..T::SERIALIZED_SIZE],
self.endianness,
)?;
self.position += T::SERIALIZED_SIZE;
Ok(result)
}
pub fn position(&self) -> usize {
self.position
}
pub fn set_position(&mut self, new_position: usize) {
self.position = new_position;
}
pub fn move_forwards(&mut self, amount: usize) {
self.position += amount;
}
pub fn move_backwards(&mut self, amount: usize) {
self.position -= amount;
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
pub fn buf(&self) -> &'a [u8] {
self.buf
}
}
#[cfg(feature = "std")]
#[derive(Clone)]
pub struct BinaryDeserializerFromStream<R: std::io::Read> {
stream: R,
endianness: Endianness,
}
#[cfg(feature = "std")]
impl<R: std::io::Read> BinaryDeserializerFromStream<R> {
pub fn new(stream: R, endianness: Endianness) -> Self {
Self { stream, endianness }
}
pub fn deserialize<T: BinarySerde>(&mut self) -> Result<T, DeserializeFromError> {
T::binary_deserialize_from(&mut self.stream, self.endianness)
}
pub fn into_stream(self) -> R {
self.stream
}
pub fn stream(&self) -> &R {
&self.stream
}
pub fn stream_mut(&mut self) -> &mut R {
&mut self.stream
}
pub fn set_endianness(&mut self, new_endianness: Endianness) {
self.endianness = new_endianness
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
}
fn get_bits_of_byte(byte: u8, start_bit_index: usize, bits_amount: usize) -> u8 {
let mask = if bits_amount == 8 {
u8::MAX
} else {
(1 << bits_amount) - 1
};
(byte >> start_bit_index) & mask
}
fn get_bits_mask(start_bit_index: usize, bits_amount: usize) -> u8 {
if bits_amount == 8 {
u8::MAX
} else {
let unshifted = (1 << bits_amount) - 1;
unshifted << start_bit_index
}
}
#[doc(hidden)]
#[derive(Clone)]
pub struct LsbBitReader<'a> {
bytes: &'a [u8],
bit_index_in_cur_byte: usize,
endianness: Endianness,
endianness_neutral_byte_index: usize,
}
impl<'a> LsbBitReader<'a> {
pub fn new(bytes: &'a [u8], endianness: Endianness) -> Self {
Self {
bytes,
bit_index_in_cur_byte: 0,
endianness,
endianness_neutral_byte_index: 0,
}
}
pub fn cur_byte_index(&self) -> usize {
match self.endianness {
Endianness::Big => self.bytes.len() - 1 - self.endianness_neutral_byte_index,
Endianness::Little => self.endianness_neutral_byte_index,
}
}
pub fn bits_left_in_cur_byte(&self) -> usize {
8 - self.bit_index_in_cur_byte
}
pub fn read_bits(&mut self, bits_amount: usize) -> u8 {
assert!(bits_amount <= self.bits_left_in_cur_byte());
let cur_byte_index = self.cur_byte_index();
let result = get_bits_of_byte(
self.bytes[cur_byte_index],
self.bit_index_in_cur_byte,
bits_amount,
);
self.bit_index_in_cur_byte += bits_amount;
if self.bit_index_in_cur_byte == 8 {
self.endianness_neutral_byte_index += 1;
self.bit_index_in_cur_byte = 0;
}
result
}
}
#[doc(hidden)]
pub struct LsbBitWriter<'a> {
bytes: &'a mut [u8],
bit_index_in_cur_byte: usize,
endianness: Endianness,
endianness_neutral_byte_index: usize,
}
impl<'a> LsbBitWriter<'a> {
pub fn new(bytes: &'a mut [u8], endianness: Endianness) -> Self {
Self {
bit_index_in_cur_byte: 0,
endianness,
endianness_neutral_byte_index: 0,
bytes,
}
}
pub fn cur_byte_index(&self) -> usize {
match self.endianness {
Endianness::Big => self.bytes.len() - 1 - self.endianness_neutral_byte_index,
Endianness::Little => self.endianness_neutral_byte_index,
}
}
pub fn bits_left_in_cur_byte(&self) -> usize {
8 - self.bit_index_in_cur_byte
}
pub fn write_bits(&mut self, bits: u8, bits_amount: usize) {
let cur_byte_index = self.cur_byte_index();
let mask = get_bits_mask(self.bit_index_in_cur_byte, bits_amount);
self.bytes[cur_byte_index] =
(self.bytes[cur_byte_index] & !mask) | (bits << self.bit_index_in_cur_byte);
self.bit_index_in_cur_byte += bits_amount;
if self.bit_index_in_cur_byte == 8 {
self.endianness_neutral_byte_index += 1;
self.bit_index_in_cur_byte = 0;
}
}
}
#[doc(hidden)]
pub fn _copy_bits<'a, 'b>(
from: &mut LsbBitReader<'a>,
to: &mut LsbBitWriter<'b>,
bits_amount: usize,
) {
let mut bits_left = bits_amount;
while bits_left > 0 {
let cur_amount = core::cmp::min(
core::cmp::min(from.bits_left_in_cur_byte(), to.bits_left_in_cur_byte()),
bits_left,
);
to.write_bits(from.read_bits(cur_amount), cur_amount);
bits_left -= cur_amount;
}
}
#[derive(Debug, Clone, Copy, Hash)]
pub struct BinarySerdePadding<const PADDING_LENGTH: usize, const PADDING_VALUE: u8>;
impl<const PADDING_LENGTH: usize, const PADDING_VALUE: u8> BinarySerde
for BinarySerdePadding<PADDING_LENGTH, PADDING_VALUE>
{
const SERIALIZED_SIZE: usize = PADDING_LENGTH;
type RecursiveArray = recursive_array_type_of_size!(u8, PADDING_LENGTH);
fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
buf[..PADDING_LENGTH].fill(PADDING_VALUE);
}
fn binary_deserialize(_buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
Ok(Self)
}
}
#[macro_export]
macro_rules! impl_binary_serde_for_bitflags_ty {
{$bitflags_ty: ty} => {
impl ::binary_serde::BinarySerde for $bitflags_ty
where
<$bitflags_ty as ::bitflags::Flags>::Bits: ::binary_serde::BinarySerde,
{
const SERIALIZED_SIZE: usize =
<<$bitflags_ty as ::bitflags::Flags>::Bits as ::binary_serde::BinarySerde>::SERIALIZED_SIZE;
type RecursiveArray =
<<$bitflags_ty as ::bitflags::Flags>::Bits as ::binary_serde::BinarySerde>::RecursiveArray;
fn binary_serialize(&self, buf: &mut [u8], endianness: ::binary_serde::Endianness) {
let bits = ::bitflags::Flags::bits(self);
::binary_serde::BinarySerde::binary_serialize(&bits, buf, endianness)
}
fn binary_deserialize(
buf: &[u8],
endianness: ::binary_serde::Endianness,
) -> Result<Self, ::binary_serde::DeserializeError> {
let bits = ::binary_serde::BinarySerde::binary_deserialize(buf, endianness)?;
Ok(::bitflags::Flags::from_bits_retain(bits))
}
fn binary_serialize_to_array(
&self,
endianness: ::binary_serde::Endianness,
) -> Self::RecursiveArray {
let bits = ::bitflags::Flags::bits(self);
::binary_serde::BinarySerde::binary_serialize_to_array(&bits, endianness)
}
}
};
}
impl BinarySerde for u8 {
const SERIALIZED_SIZE: usize = 1;
type RecursiveArray = RecursiveArraySingleItem<u8>;
fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
buf[0] = *self;
}
fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
RecursiveArraySingleItem::new(*self)
}
#[cfg(feature = "std")]
fn binary_serialize_into<W: std::io::Write>(
&self,
stream: &mut W,
_endianness: Endianness,
) -> std::io::Result<()> {
stream.write_all(&[*self])
}
fn binary_deserialize(buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
Ok(buf[0])
}
#[cfg(feature = "std")]
fn binary_deserialize_from<R: std::io::Read>(
stream: &mut R,
_endianness: Endianness,
) -> Result<Self, DeserializeFromError> {
let mut result: core::mem::MaybeUninit<Self> = core::mem::MaybeUninit::uninit();
stream.read_exact(unsafe { core::slice::from_raw_parts_mut(result.as_mut_ptr(), 1) })?;
Ok(unsafe { result.assume_init() })
}
}
impl BinarySerde for i8 {
const SERIALIZED_SIZE: usize = 1;
type RecursiveArray = RecursiveArraySingleItem<u8>;
fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
buf[0] = *self as u8;
}
fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
RecursiveArraySingleItem::new(*self as u8)
}
#[cfg(feature = "std")]
fn binary_serialize_into<W: std::io::Write>(
&self,
stream: &mut W,
_endianness: Endianness,
) -> std::io::Result<()> {
stream.write_all(&[*self as u8])
}
fn binary_deserialize(buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
Ok(buf[0] as i8)
}
#[cfg(feature = "std")]
fn binary_deserialize_from<R: std::io::Read>(
stream: &mut R,
_endianness: Endianness,
) -> Result<Self, DeserializeFromError> {
let mut result: core::mem::MaybeUninit<u8> = core::mem::MaybeUninit::uninit();
stream.read_exact(unsafe { core::slice::from_raw_parts_mut(result.as_mut_ptr(), 1) })?;
let byte = unsafe { result.assume_init() };
Ok(byte as i8)
}
}
impl BinarySerde for bool {
const SERIALIZED_SIZE: usize = 1;
type RecursiveArray = RecursiveArraySingleItem<u8>;
fn binary_serialize(&self, buf: &mut [u8], _endianness: Endianness) {
buf[0] = *self as u8;
}
fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
RecursiveArraySingleItem::new(*self as u8)
}
#[cfg(feature = "std")]
fn binary_serialize_into<W: std::io::Write>(
&self,
stream: &mut W,
_endianness: Endianness,
) -> std::io::Result<()> {
stream.write_all(&[*self as u8])
}
fn binary_deserialize(buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
Ok(buf[0] != 0)
}
#[cfg(feature = "std")]
fn binary_deserialize_from<R: std::io::Read>(
stream: &mut R,
_endianness: Endianness,
) -> Result<Self, DeserializeFromError> {
let mut result: core::mem::MaybeUninit<u8> = core::mem::MaybeUninit::uninit();
stream.read_exact(unsafe { core::slice::from_raw_parts_mut(result.as_mut_ptr(), 1) })?;
let byte = unsafe { result.assume_init() };
Ok(byte != 0)
}
}
impl<T> BinarySerde for PhantomData<T> {
const SERIALIZED_SIZE: usize = 0;
type RecursiveArray = EmptyRecursiveArray;
fn binary_serialize(&self, _buf: &mut [u8], _endianness: Endianness) {}
fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
EmptyRecursiveArray
}
#[cfg(feature = "std")]
fn binary_serialize_into<W: std::io::Write>(
&self,
_stream: &mut W,
_endianness: Endianness,
) -> std::io::Result<()> {
Ok(())
}
fn binary_deserialize(_buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
Ok(Self)
}
#[cfg(feature = "std")]
fn binary_deserialize_from<R: std::io::Read>(
_stream: &mut R,
_endianness: Endianness,
) -> Result<Self, DeserializeFromError> {
Ok(Self)
}
}
impl BinarySerde for () {
const SERIALIZED_SIZE: usize = 0;
type RecursiveArray = EmptyRecursiveArray;
fn binary_serialize(&self, _buf: &mut [u8], _endianness: Endianness) {}
fn binary_serialize_to_array(&self, _endianness: Endianness) -> Self::RecursiveArray {
EmptyRecursiveArray
}
#[cfg(feature = "std")]
fn binary_serialize_into<W: std::io::Write>(
&self,
_stream: &mut W,
_endianness: Endianness,
) -> std::io::Result<()> {
Ok(())
}
fn binary_deserialize(_buf: &[u8], _endianness: Endianness) -> Result<Self, DeserializeError> {
Ok(())
}
#[cfg(feature = "std")]
fn binary_deserialize_from<R: std::io::Read>(
_stream: &mut R,
_endianness: Endianness,
) -> Result<Self, DeserializeFromError> {
Ok(())
}
}
impl<const N: usize, T: BinarySerde> BinarySerde for [T; N] {
const SERIALIZED_SIZE: usize = T::SERIALIZED_SIZE * N;
type RecursiveArray = RecursiveArrayMultiplier<N, u8, T::RecursiveArray>;
fn binary_serialize(&self, buf: &mut [u8], endianness: Endianness) {
struct ZipExact<A: Iterator, B: Iterator> {
a: A,
b: B,
}
impl<A: Iterator, B: Iterator> Iterator for ZipExact<A, B> {
type Item = (A::Item, B::Item);
fn next(&mut self) -> Option<Self::Item> {
match (self.a.next(), self.b.next()) {
(Some(a), Some(b)) => Some((a, b)),
(None, None) => None,
_ => panic!("zipped iterators are of different lengths"),
}
}
}
fn zip_exact<A: Iterator, B: Iterator>(a: A, b: B) -> ZipExact<A, B> {
ZipExact { a, b }
}
for (item, item_buf) in zip_exact(self.iter(), buf.chunks_mut(T::SERIALIZED_SIZE)) {
item.binary_serialize(item_buf, endianness)
}
}
fn binary_deserialize(buf: &[u8], endianness: Endianness) -> Result<Self, DeserializeError> {
array_init::try_array_init(|i| {
T::binary_deserialize(
&buf[i * T::SERIALIZED_SIZE..][..T::SERIALIZED_SIZE],
endianness,
)
})
}
}
macro_rules! impl_for_primitive_types {
{$($type: ty),+} => {
$(
impl BinarySerde for $type {
const SERIALIZED_SIZE: usize = core::mem::size_of::<Self>();
type RecursiveArray = recursive_array_type_of_size!(u8, core::mem::size_of::<Self>());
fn binary_serialize(&self, buf: &mut [u8], endianness: Endianness) {
let bytes = match endianness {
Endianness::Big => self.to_be_bytes(),
Endianness::Little => self.to_le_bytes(),
};
buf.copy_from_slice(bytes.as_slice());
}
fn binary_deserialize(buf: &[u8], endianness: Endianness) -> Result<Self, DeserializeError> {
let array = buf.try_into().unwrap();
Ok(match endianness {
Endianness::Big => Self::from_be_bytes(array),
Endianness::Little => Self::from_le_bytes(array),
})
}
}
)+
};
}
impl_for_primitive_types! {u16,u32,u64,u128,i16,i32,i64,i128,f32,f64}