use crate::error::DecodeError;
pub const MAX_DECODE_DEPTH: u32 = 64;
pub const DEFAULT_COLLECTION_LIMIT: u32 = 64_000_000;
pub struct BufDecoder<'buf> {
buf: &'buf [u8],
pos: usize,
depth: u32,
collection_limit: u32,
}
impl<'buf> BufDecoder<'buf> {
#[inline]
pub fn new(buf: &'buf [u8]) -> Self {
Self { buf, pos: 0, depth: 0, collection_limit: DEFAULT_COLLECTION_LIMIT }
}
#[inline]
pub fn with_collection_limit(mut self, limit: u32) -> Self {
self.collection_limit = limit;
self
}
#[inline]
pub fn collection_limit(&self) -> u32 {
self.collection_limit
}
#[inline]
pub fn position(&self) -> usize {
self.pos
}
#[inline]
pub fn remaining(&self) -> usize {
self.buf.len().saturating_sub(self.pos)
}
#[inline]
pub fn read_bytes(&mut self, n: usize) -> Result<&'buf [u8], DecodeError> {
let end = self.pos.checked_add(n).filter(|&e| e <= self.buf.len()).ok_or(DecodeError::UnexpectedEof {
needed: n,
remaining: self.remaining(),
})?;
let slice = &self.buf[self.pos..end];
self.pos = end;
Ok(slice)
}
#[inline]
pub fn read_u8(&mut self) -> Result<u8, DecodeError> {
Ok(self.read_bytes(1)?[0])
}
#[inline]
pub fn read_u16(&mut self) -> Result<u16, DecodeError> {
let b = self.read_bytes(2)?;
Ok(u16::from_le_bytes([b[0], b[1]]))
}
#[inline]
pub fn read_u32(&mut self) -> Result<u32, DecodeError> {
let b = self.read_bytes(4)?;
Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
}
#[inline]
pub fn read_u64(&mut self) -> Result<u64, DecodeError> {
let b = self.read_bytes(8)?;
Ok(u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]))
}
#[inline]
pub fn enter(&mut self) -> Result<(), DecodeError> {
if self.depth >= MAX_DECODE_DEPTH {
return Err(DecodeError::NestingTooDeep);
}
self.depth += 1;
Ok(())
}
#[inline]
pub fn leave(&mut self) {
debug_assert!(self.depth > 0, "leave() called without matching enter()");
self.depth = self.depth.saturating_sub(1);
}
}