use crate::{Error, Result};
pub trait Bytes: Sized {
type Array: AsRef<[u8]>;
const IS_NATIVE_LAYOUT: bool = false;
fn to_bytes(&self) -> Self::Array;
fn from_bytes(bytes: &[u8]) -> Result<Self>;
}
macro_rules! impl_bytes_for_numeric {
($($t:ty),*) => {
$(
impl Bytes for $t {
type Array = [u8; std::mem::size_of::<$t>()];
const IS_NATIVE_LAYOUT: bool = cfg!(target_endian = "little");
#[inline]
fn to_bytes(&self) -> Self::Array {
self.to_le_bytes()
}
#[inline]
fn from_bytes(bytes: &[u8]) -> Result<Self> {
let arr: [u8; std::mem::size_of::<$t>()] = bytes
.try_into()
.map_err(|_| Error::WrongLength {
expected: std::mem::size_of::<$t>(),
received: bytes.len(),
})?;
Ok(<$t>::from_le_bytes(arr))
}
}
)*
};
}
impl_bytes_for_numeric!(
u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64
);
macro_rules! impl_bytes_for_array {
($($n:expr),*) => {
$(
impl Bytes for [u8; $n] {
type Array = [u8; $n];
const IS_NATIVE_LAYOUT: bool = true;
#[inline]
fn to_bytes(&self) -> Self::Array {
*self
}
#[inline]
fn from_bytes(bytes: &[u8]) -> Result<Self> {
bytes.try_into().map_err(|_| Error::WrongLength {
expected: $n,
received: bytes.len(),
})
}
}
)*
};
}
impl_bytes_for_array!(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 64, 65
);