use crate::{
endian::{Big, Little},
slice::initialize_with,
BitSlice, Collum, Sized,
};
macro_rules! impl_collum_big_endian {
($($type:ty),*) => {
$(
impl Collum for Big<$type> {
fn take_from_bit_slice(slice: BitSlice) -> Option<(Self, BitSlice)> {
let val = Big(<$type>::from_be_bytes(slice.copy_array()?));
let slice = slice.get(<$type>::least_bytes()..)?;
Some((val, slice))
}
}
)*
}
}
macro_rules! impl_collum_little_endian {
($($type:ty),*) => {
$(
impl Collum for Little<$type> {
fn take_from_bit_slice(slice: BitSlice) -> Option<(Self, BitSlice)> {
let val = Little(<$type>::from_le_bytes(slice.copy_array()?));
let slice = slice.get(<$type>::least_bytes()..)?;
Some((val, slice))
}
}
)*
}
}
macro_rules! impl_collum_native_endian {
($($type:ty),*) => {
$(
impl Collum for $type {
fn take_from_bit_slice(slice: BitSlice) -> Option<(Self, BitSlice)> {
let val = <$type>::from_ne_bytes(slice.copy_array()?);
let slice = slice.get(<$type>::least_bytes()..)?;
Some((val, slice))
}
}
)*
}
}
impl_collum_big_endian!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
impl_collum_little_endian!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
impl_collum_native_endian!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
impl Collum for bool {
fn take_from_bit_slice(slice: BitSlice) -> Option<(Self, BitSlice)> {
if slice.bits() < 1 {
return None;
}
let [b] = slice.copy_bits(1)?;
Some((b != 0, slice.offset_by_sized::<bool>()?))
}
}
impl<T, const N: usize> Collum for [T; N]
where
T: Collum,
{
fn take_from_bit_slice(mut slice: BitSlice) -> Option<(Self, BitSlice)> {
if slice.bits() < Self::bits() {
return None;
}
let ret: [T; N] = initialize_with(|| {
let val;
(val, slice) = T::take_from_bit_slice(slice).expect("Array bounds checked");
val
});
Some((ret, slice))
}
}