kazari 0.0.1

A no_std GUI software stack (Work-in-Progress)
Documentation
use core::convert::TryInto;

fn align_down(value: usize, align: usize) -> usize {
    value & !(align - 1)
}

fn align_up(value: usize, align: usize) -> usize {
    align_down(value + align - 1, align)
}

#[derive(Debug, PartialEq)]
pub enum BytesReaderError {
    TooShort,
}

pub struct BytesReader<'a> {
    bytes: &'a [u8],
    current: usize,
}

impl<'a> BytesReader<'a> {
    pub fn new(bytes: &[u8]) -> BytesReader<'_> {
        BytesReader { bytes, current: 0 }
    }

    pub fn remaining(&self) -> &[u8] {
        &self.bytes[self.current..]
    }

    pub fn remaining_len(&self) -> usize {
        self.bytes.len() - self.current
    }

    pub fn skip(&mut self, len: usize) -> Result<(), BytesReaderError> {
        if self.current + len > self.bytes.len() {
            return Err(BytesReaderError::TooShort);
        }

        self.current += len;
        Ok(())
    }

    pub fn skip_until_alignment(&mut self, align: usize) -> Result<(), BytesReaderError> {
        let next = align_up(self.current, align);
        if next > self.bytes.len() {
            return Err(BytesReaderError::TooShort);
        }

        self.current = next;
        Ok(())
    }

    pub fn consume_le_u16(&mut self) -> Result<u16, BytesReaderError> {
        if self.remaining_len() < 2 {
            return Err(BytesReaderError::TooShort);
        }

        let value = u16::from_le_bytes(
            self.bytes[self.current..self.current + 2]
                .try_into()
                .unwrap(),
        );
        self.current += 2;
        Ok(value)
    }

    pub fn consume_le_u32(&mut self) -> Result<u32, BytesReaderError> {
        if self.remaining_len() < 4 {
            return Err(BytesReaderError::TooShort);
        }

        let value = u32::from_le_bytes(
            self.bytes[self.current..self.current + 4]
                .try_into()
                .unwrap(),
        );
        self.current += 4;
        Ok(value)
    }

    pub fn consume_le_i32(&mut self) -> Result<i32, BytesReaderError> {
        if self.remaining_len() < 4 {
            return Err(BytesReaderError::TooShort);
        }

        let value = i32::from_le_bytes(
            self.bytes[self.current..self.current + 4]
                .try_into()
                .unwrap(),
        );
        self.current += 4;
        Ok(value)
    }
}