use lerc_core::{Error, Result};
#[derive(Clone, Copy)]
pub(crate) struct Cursor<'a> {
bytes: &'a [u8],
offset: usize,
}
impl<'a> Cursor<'a> {
pub(crate) fn new(bytes: &'a [u8]) -> Self {
Self { bytes, offset: 0 }
}
pub(crate) fn remaining(&self) -> usize {
self.bytes.len().saturating_sub(self.offset)
}
pub(crate) fn offset(&self) -> usize {
self.offset
}
pub(crate) fn read_bytes(&mut self, len: usize) -> Result<&'a [u8]> {
let end = self
.offset
.checked_add(len)
.ok_or_else(|| Error::InvalidBlob("offset overflow".into()))?;
if end > self.bytes.len() {
return Err(Error::Truncated {
offset: self.offset,
needed: len,
available: self.bytes.len().saturating_sub(self.offset),
});
}
let out = &self.bytes[self.offset..end];
self.offset = end;
Ok(out)
}
pub(crate) fn skip(&mut self, len: usize) -> Result<()> {
self.read_bytes(len).map(|_| ())
}
pub(crate) fn read_u8(&mut self) -> Result<u8> {
Ok(self.read_bytes(1)?[0])
}
pub(crate) fn read_u32(&mut self) -> Result<u32> {
Ok(u32::from_le_bytes(self.read_bytes(4)?.try_into().unwrap()))
}
pub(crate) fn read_f32(&mut self) -> Result<f32> {
Ok(f32::from_le_bytes(self.read_bytes(4)?.try_into().unwrap()))
}
pub(crate) fn read_i16(&mut self) -> Result<i16> {
Ok(i16::from_le_bytes(self.read_bytes(2)?.try_into().unwrap()))
}
pub(crate) fn read_i32(&mut self) -> Result<i32> {
Ok(i32::from_le_bytes(self.read_bytes(4)?.try_into().unwrap()))
}
pub(crate) fn read_f64(&mut self) -> Result<f64> {
Ok(f64::from_le_bytes(self.read_bytes(8)?.try_into().unwrap()))
}
}