use std::mem::MaybeUninit;
pub trait NinBytes<'a> {
type Bytes: AsRef<[u8]>;
fn as_bytes(&'a self) -> Self::Bytes;
fn from_bytes(b: Self::Bytes) -> Self;
}
macro_rules! impl_bytes {
(be_bytes $T:ty => $R:ty) => {
impl<'a> NinBytes<'a> for $T {
type Bytes = $R;
fn as_bytes(&'a self) -> Self::Bytes {
self.to_be_bytes()
}
fn from_bytes(b: Self::Bytes) -> Self {
Self::from_be_bytes(b)
}
}
};
(deref $r:lifetime $T:ty => $R:ty) => {
impl<$r> NinBytes<$r> for $T {
type Bytes = $R;
fn as_bytes(&$r self) -> Self::Bytes {
&*self
}
fn from_bytes(b: Self::Bytes) -> Self {
b.into()
}
}
};
}
impl_bytes!(be_bytes i8 => [u8; 1]);
impl_bytes!(be_bytes u8 => [u8; 1]);
impl_bytes!(be_bytes i16 => [u8; 2]);
impl_bytes!(be_bytes u16 => [u8; 2]);
impl_bytes!(be_bytes i32 => [u8; 4]);
impl_bytes!(be_bytes u32 => [u8; 4]);
impl_bytes!(be_bytes i64 => [u8; 8]);
impl_bytes!(be_bytes u64 => [u8; 8]);
impl_bytes!(be_bytes i128 => [u8; 16]);
impl_bytes!(be_bytes u128 => [u8; 16]);
impl_bytes!(be_bytes f32 => [u8; 4]);
impl_bytes!(be_bytes f64 => [u8; 8]);
impl_bytes!(deref 'a &'a [u8] => &'a [u8]);
impl_bytes!(deref 'a Vec<u8> => &'a [u8]);
impl<'a, const N: usize> NinBytes<'a> for [u8; N] {
type Bytes = [u8; N];
fn as_bytes(&'a self) -> Self::Bytes {
*self
}
fn from_bytes(b: Self::Bytes) -> Self {
b
}
}
pub const fn concat_arrays<T: Copy, const A: usize, const B: usize, const C: usize>(a: [T; A], b: [T; B]) -> [T; C] {
const {
if A + B != C {
panic!("concatenated array size mismatch");
}
}
let mut result = [MaybeUninit::<T>::uninit(); C];
let mut i = 0;
while i < A {
result[i] = MaybeUninit::new(a[i]);
i += 1;
}
while i < C {
result[i] = MaybeUninit::new(b[i - A]);
i += 1;
}
unsafe { *(&raw const result as *const [T; C]) }
}