use crate::{Bytes, Error, Result, SIZE_OF_U64, Stamp};
pub(crate) struct ChangeCursor<'a> {
bytes: &'a [u8],
pos: usize,
}
impl<'a> ChangeCursor<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
Self { bytes, pos: 0 }
}
pub fn read_u64(&mut self) -> Result<usize> {
self.check_remaining(SIZE_OF_U64)?;
let v = usize::from_bytes(&self.bytes[self.pos..self.pos + SIZE_OF_U64])?;
self.pos += SIZE_OF_U64;
Ok(v)
}
pub fn read_stamp(&mut self) -> Result<Stamp> {
self.check_remaining(SIZE_OF_U64)?;
let v = Stamp::from_bytes(&self.bytes[self.pos..self.pos + SIZE_OF_U64])?;
self.pos += SIZE_OF_U64;
Ok(v)
}
pub fn skip(&mut self, n: usize) -> Result<()> {
self.check_remaining(n)?;
self.pos += n;
Ok(())
}
pub fn read_values<T, F: FnMut(&[u8]) -> Result<T>>(
&mut self,
count: usize,
size_of_t: usize,
mut read: F,
) -> Result<Vec<T>> {
let total = size_of_t.checked_mul(count).ok_or(Error::Overflow)?;
self.check_remaining(total)?;
let vals = self.bytes[self.pos..self.pos + total]
.chunks(size_of_t)
.map(&mut read)
.collect::<Result<Vec<_>>>()?;
self.pos += total;
Ok(vals)
}
fn check_remaining(&self, len: usize) -> Result<()> {
let end = self.pos.checked_add(len).ok_or(Error::Overflow)?;
if end > self.bytes.len() {
return Err(Error::WrongLength {
received: self.bytes.len(),
expected: end,
});
}
Ok(())
}
}