pub(super) struct Reader<'a> {
b: &'a [u8],
p: usize,
}
impl<'a> Reader<'a> {
#[allow(dead_code)] pub(super) fn new(b: &'a [u8]) -> Self {
Self { b, p: 0 }
}
pub(super) fn at(b: &'a [u8], p: usize) -> Self {
Self { b, p }
}
pub(super) fn pos(&self) -> usize {
self.p
}
pub(super) fn take(&mut self, n: usize) -> Result<&'a [u8], String> {
let end = self.p.checked_add(n).ok_or("truncated chunk")?;
let slice = self.b.get(self.p..end).ok_or("truncated chunk")?;
self.p = end;
Ok(slice)
}
pub(super) fn u8(&mut self) -> Result<u8, String> {
Ok(self.take(1)?[0])
}
pub(super) fn u32(&mut self) -> Result<u32, String> {
Ok(u32::from_le_bytes(self.take(4)?.try_into().unwrap()))
}
pub(super) fn bytes(&mut self) -> Result<&'a [u8], String> {
let n = self.u32()? as usize;
self.take(n)
}
#[allow(dead_code)]
pub(super) fn peek_underlying_slice(&self) -> &'a [u8] {
self.b
}
#[allow(dead_code)]
pub(super) fn skip_to(&mut self, to: usize) -> Result<(), String> {
if to < self.p || to > self.b.len() {
return Err(format!(
"skip_to {to} out of range (cur {}, len {})",
self.p,
self.b.len()
));
}
self.p = to;
Ok(())
}
}
#[allow(dead_code)] pub(super) fn read_puc_varint(r: &mut Reader) -> Result<u64, String> {
let mut acc: u64 = 0;
for _ in 0..10 {
let byte = r.u8()?;
if acc >> 57 != 0 {
return Err("puc varint value overflows u64".to_string());
}
acc = (acc << 7) | (byte & 0x7f) as u64;
if byte & 0x80 == 0 {
return Ok(acc);
}
}
Err("puc varint value too long (max 10 bytes)".to_string())
}