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);