collum 0.1.0

A crate for cleanly describing and parsing bit-wide data structures
Documentation
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))
    }
}