oca 0.2.0

An experiment with no_std
Documentation
use {super::Error, core::mem::size_of};

pub const fn take(input: &[u8], n: usize) -> Result<(&[u8], &[u8]), Error> {
    if input.len() >= n {
        Ok(input.split_at(n))
    } else {
        Err(Error::IncompleteInput)
    }
}

pub trait ParseResultExt<'a, A> {
    fn map_value<B>(self, f: impl FnOnce(A) -> B) -> Result<(B, &'a [u8]), Error>;

    fn try_map_value<B, E>(self, f: impl FnOnce(A) -> Result<B, E>) -> Result<(B, &'a [u8]), Error>
    where
        Error: From<E>;
}

impl<'a, A> ParseResultExt<'a, A> for Result<(A, &'a [u8]), Error> {
    fn map_value<B>(self, f: impl FnOnce(A) -> B) -> Result<(B, &'a [u8]), Error> {
        self.map(|(a, remaining)| (f(a), remaining))
    }

    fn try_map_value<B, E>(self, f: impl FnOnce(A) -> Result<B, E>) -> Result<(B, &'a [u8]), Error>
    where
        Error: From<E>,
    {
        self.and_then(|(a, remaining)| Ok((f(a)?, remaining)))
    }
}

macro_rules! bytes_to_int {
    ($int:ty, $name:ident) => {
        pub const fn $name(input: &[u8]) -> Result<($int, &[u8]), Error> {
            match take(input, size_of::<$int>()) {
                Ok((input, remaining)) => {
                    let mut buffer = [0u8; size_of::<$int>()];
                    buffer.as_mut_slice().copy_from_slice(input);

                    Ok((<$int>::from_be_bytes(buffer), remaining))
                }
                Err(err) => Err(err),
            }
        }
    };
}

bytes_to_int!(u8, u8);
bytes_to_int!(u16, be_u16);
bytes_to_int!(u32, be_u32);