#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CursorError {
UnexpectedEof,
}
pub struct Cursor<T> {
inner: T,
pos: u64,
}
impl<T> Cursor<T> {
#[inline]
pub fn new(inner: T) -> Self {
Cursor { inner, pos: 0 }
}
#[inline]
pub fn position(&self) -> u64 {
self.pos
}
#[inline]
pub fn set_position(&mut self, pos: u64) {
self.pos = pos;
}
#[inline]
pub fn get_ref(&self) -> &T {
&self.inner
}
}
impl Cursor<&[u8]> {
#[inline]
pub fn remaining_slice(&self) -> &[u8] {
let pos = self.pos as usize;
if pos <= self.inner.len() {
&self.inner[pos..]
} else {
&[]
}
}
#[inline]
pub fn read_bytes(&mut self, count: usize) -> Option<&[u8]> {
let pos = self.pos as usize;
if pos.saturating_add(count) <= self.inner.len() {
let data = &self.inner[pos..pos + count];
self.pos += count as u64;
Some(data)
} else {
None
}
}
#[inline]
pub fn read_u8(&mut self) -> Option<u8> {
let pos = self.pos as usize;
if pos < self.inner.len() {
let val = self.inner[pos];
self.pos += 1;
Some(val)
} else {
None
}
}
}
impl<T: AsRef<[u8]>> Cursor<T> {
#[inline]
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, CursorError> {
let pos = self.pos as usize;
let available = self.inner.as_ref().len().saturating_sub(pos);
let to_read = core::cmp::min(buf.len(), available);
if to_read > 0 {
buf[..to_read].copy_from_slice(&self.inner.as_ref()[pos..pos + to_read]);
self.pos += to_read as u64;
}
Ok(to_read)
}
#[inline]
pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), CursorError> {
let pos = self.pos as usize;
let available = self.inner.as_ref().len().saturating_sub(pos);
if available < buf.len() {
return Err(CursorError::UnexpectedEof);
}
buf.copy_from_slice(&self.inner.as_ref()[pos..pos + buf.len()]);
self.pos += buf.len() as u64;
Ok(())
}
}