mbn 1.0.2

MBN format parse library
Documentation
use crate::error::ParseError;

pub(crate) trait ByteRead: Sized {
    fn read(buffer: &ByteReader<'_>) -> crate::Result<(Self, usize)>;
}

#[derive(Clone)]
pub(crate) struct ByteReader<'a> {
    buffer: &'a [u8],
    offset: usize,
}

impl<'a> ByteReader<'a> {
    pub fn new(buffer: &'a [u8]) -> ByteReader<'a> {
        Self { buffer, offset: 0 }
    }

    pub fn current(&self) -> &[u8] {
        &self.buffer[self.offset..]
    }

    pub fn available(&self) -> usize {
        self.buffer.len() - self.offset
    }

    pub fn peek<T: ByteRead>(&self, offset: usize) -> crate::Result<T> {
        let mut reader = self.clone();
        reader.skip(offset)?;
        T::read(&reader).map(|(t, _)| t)
    }

    pub fn read<T: ByteRead>(&mut self) -> crate::Result<T> {
        let (t, count) = T::read(self)?;
        self.offset += count;
        Ok(t)
    }

    pub fn skip(&mut self, count: usize) -> crate::Result<Vec<u8>> {
        if self.offset + count > self.buffer.len() {
            Err(ParseError::InputUnexpectedTermination)
        } else {
            let v = self.buffer[self.offset..self.offset + count].to_vec();
            self.offset += count;
            Ok(v)
        }
    }
}

impl ByteRead for u8 {
    fn read(buffer: &ByteReader<'_>) -> crate::Result<(Self, usize)> {
        Ok((
            *(buffer
                .current()
                .first()
                .ok_or(ParseError::InputUnexpectedTermination)?),
            1,
        ))
    }
}

impl ByteRead for u32 {
    fn read(buffer: &ByteReader<'_>) -> crate::Result<(Self, usize)> {
        Ok((
            u32::from_le_bytes(
                buffer
                    .current()
                    .get(0..std::mem::size_of::<Self>())
                    .ok_or(ParseError::InputUnexpectedTermination)?
                    .try_into()
                    .unwrap(),
            ),
            std::mem::size_of::<Self>(),
        ))
    }
}

impl<const N: usize> ByteRead for [u8; N] {
    fn read(buffer: &ByteReader<'_>) -> crate::Result<(Self, usize)> {
        Ok((
            buffer
                .current()
                .get(0..std::mem::size_of::<Self>())
                .ok_or(ParseError::InputUnexpectedTermination)?
                .try_into()
                .unwrap(),
            N,
        ))
    }
}