use crate::{Error, util};
#[derive(Debug)]
pub struct Reader<'a> {
data: &'a [u8],
cursor: usize,
}
impl<'a> Reader<'a> {
pub const fn new(data: &'a [u8], offset: usize) -> Self {
Self {
data,
cursor: offset,
}
}
pub const fn position(&self) -> usize {
self.cursor
}
pub fn remaining(&self) -> usize {
self.data.len().saturating_sub(self.cursor)
}
pub fn range(&self, start: usize, end: usize) -> Option<&'a [u8]> {
self.data.get(start..end)
}
pub fn read_u8(&mut self) -> Result<u8, Error> {
let bytes = self.read_bytes(1)?;
bytes.first().copied().ok_or_else(Error::truncated)
}
pub fn read_u32_le(&mut self) -> Result<u32, Error> {
let offset = self.cursor;
let value = util::read_u32_le(self.data, offset).ok_or_else(Error::truncated)?;
self.cursor = self.cursor.checked_add(4).ok_or_else(Error::truncated)?;
Ok(value)
}
pub fn read_u64_le(&mut self) -> Result<u64, Error> {
let low = u64::from(self.read_u32_le()?);
let high = u64::from(self.read_u32_le()?);
Ok(low | (high << 32))
}
pub fn read_bytes(&mut self, len: usize) -> Result<&'a [u8], Error> {
let end = self.cursor.checked_add(len).ok_or_else(Error::truncated)?;
let bytes = self
.data
.get(self.cursor..end)
.ok_or_else(Error::truncated)?;
self.cursor = end;
Ok(bytes)
}
}