wireparse 0.1.0

Library for reading and writing ethernet and other related protocals.
Documentation
use core::{mem::MaybeUninit, usize};

pub trait UncheckedReader<'a>: Sized {
    fn read_slice_unchecked(&mut self, size: usize) -> &'a [u8];
    fn read_fixed_slice_unchecked<const N: usize>(&mut self) -> &'a [u8; N];

    #[inline(always)]
    fn read_unchecked<T: ReadDataUnchecked<'a>>(&mut self) -> T {
        T::read_unchecked(self)
    }

    fn length(&self) -> usize;
}

pub trait UncheckedWriter: Sized {
    fn write_slice_unchecked(&mut self, data: &[u8]);
    #[inline(always)]
    fn write_unchecked<T: WriteDataUnchecked>(&mut self, value: T) {
        T::write_to_unchecked(value, self)
    }
}

impl<'a> UncheckedReader<'a> for &'a [u8] {
    #[inline(always)]
    fn read_slice_unchecked(&mut self, size: usize) -> &'a [u8] {
        let (data, remaining) = self.split_at(size);
        *self = remaining;
        data
    }

    #[inline(always)]
    fn read_fixed_slice_unchecked<const N: usize>(&mut self) -> &'a [u8; N] {
        let (data, remaining) = self.split_at(N);
        *self = remaining;
        data.first_chunk().unwrap()
    }

    fn length(&self) -> usize {
        self.len()
    }
}

impl<'a> UncheckedWriter for &'a mut [u8] {
    #[inline(always)]
    fn write_slice_unchecked(&mut self, data: &[u8]) {
        let this = core::mem::take(self);
        let (write_buffer, remaining) = this.split_at_mut(data.len());
        *self = remaining;
        write_buffer.copy_from_slice(data);
    }
}

pub trait ReadDataUnchecked<'a>: Sized {
    fn read_unchecked(reader: &mut impl UncheckedReader<'a>) -> Self;
}

pub trait WriteDataUnchecked {
    fn write_to_unchecked(self, writer: &mut impl UncheckedWriter);
}

impl<'a, const N: usize> ReadDataUnchecked<'a> for [u8; N] {
    #[inline(always)]
    fn read_unchecked(reader: &mut impl UncheckedReader<'a>) -> Self {
        let slice = reader.read_slice_unchecked(N);
        unsafe { *slice.as_ptr().cast() }
    }
}

impl<const N: usize> WriteDataUnchecked for [u8; N] {
    fn write_to_unchecked(self, writer: &mut impl UncheckedWriter) {
        writer.write_slice_unchecked(&self)
    }
}

impl<'a, const N: usize> ReadDataUnchecked<'a> for [u16; N] {
    fn read_unchecked(reader: &mut impl UncheckedReader<'a>) -> Self {
        let mut read_buffer = reader.read_slice_unchecked(core::mem::size_of::<u16>() * N);
        let mut write_buffer: [MaybeUninit<u16>; N] =
            unsafe { MaybeUninit::uninit().assume_init() };
        let read_ptr = &mut read_buffer;

        for elem in write_buffer.iter_mut() {
            elem.write(u16::read_unchecked(read_ptr));
        }

        unsafe { *write_buffer.as_ptr().cast() }
    }
}
impl<const N: usize> WriteDataUnchecked for [u16; N] {
    fn write_to_unchecked(self, writer: &mut impl UncheckedWriter) {
        for v in self.iter() {
            writer.write_unchecked(*v);
        }
    }
}

impl<'a> ReadDataUnchecked<'a> for u8 {
    fn read_unchecked(reader: &mut impl UncheckedReader<'a>) -> Self {
        reader.read_slice_unchecked(1)[0]
    }
}

impl WriteDataUnchecked for u8 {
    fn write_to_unchecked(self, writer: &mut impl UncheckedWriter) {
        writer.write_slice_unchecked(&[self])
    }
}

macro_rules! impl_read_write_data_unchecked {
    ($($t:ty),+) => {
        $(
            impl<'a> ReadDataUnchecked<'a> for $t {
                #[inline(always)]
                fn read_unchecked(reader: &mut impl UncheckedReader<'a>) -> $t {
                        let data = reader.read_unchecked();
                        <$t>::from_be_bytes(data)
                }
            }

            impl WriteDataUnchecked for $t {
                #[inline(always)]
                fn write_to_unchecked(self, writer: &mut impl UncheckedWriter) {
                    let data = self.to_be_bytes();
                    writer.write_unchecked(data)
                }
            }
         )*
    };
}

impl_read_write_data_unchecked! {
    u16,
    u32,
    u64
}