use crate::error::DecodeError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Limits {
pub max_string_len: usize,
pub max_bytes_len: usize,
pub max_array_count: usize,
}
impl Limits {
pub const UNLIMITED: Limits = Limits {
max_string_len: u32::MAX as usize,
max_bytes_len: u32::MAX as usize,
max_array_count: u32::MAX as usize,
};
}
impl Default for Limits {
#[inline]
fn default() -> Self {
Limits::UNLIMITED
}
}
#[derive(Debug, Clone)]
pub struct Reader<'a> {
buf: &'a [u8],
pos: usize,
limits: Limits,
}
impl<'a> Reader<'a> {
#[inline]
pub fn new(buf: &'a [u8]) -> Self {
Reader { buf, pos: 0, limits: Limits::UNLIMITED }
}
#[inline]
pub fn with_limits(buf: &'a [u8], limits: Limits) -> Self {
Reader { buf, pos: 0, limits }
}
#[inline]
pub fn position(&self) -> usize {
self.pos
}
#[inline]
pub fn remaining(&self) -> usize {
self.buf.len() - self.pos
}
#[inline]
pub fn is_empty(&self) -> bool {
self.remaining() == 0
}
#[inline]
pub fn limits(&self) -> Limits {
self.limits
}
#[inline]
pub fn read_bool(&mut self) -> Result<bool, DecodeError> {
let byte = self.read_u8()?;
match byte {
0x00 => Ok(false),
0x01 => Ok(true),
other => {
self.pos -= 1;
Err(DecodeError::InvalidBool(other))
}
}
}
#[inline]
pub fn read_i8(&mut self) -> Result<i8, DecodeError> {
Ok(i8::from_le_bytes(*self.take::<1>()?))
}
#[inline]
pub fn read_u8(&mut self) -> Result<u8, DecodeError> {
Ok(u8::from_le_bytes(*self.take::<1>()?))
}
#[inline]
pub fn read_i16(&mut self) -> Result<i16, DecodeError> {
Ok(i16::from_le_bytes(*self.take::<2>()?))
}
#[inline]
pub fn read_u16(&mut self) -> Result<u16, DecodeError> {
Ok(u16::from_le_bytes(*self.take::<2>()?))
}
#[inline]
pub fn read_i32(&mut self) -> Result<i32, DecodeError> {
Ok(i32::from_le_bytes(*self.take::<4>()?))
}
#[inline]
pub fn read_u32(&mut self) -> Result<u32, DecodeError> {
Ok(u32::from_le_bytes(*self.take::<4>()?))
}
#[inline]
pub fn read_i64(&mut self) -> Result<i64, DecodeError> {
Ok(i64::from_le_bytes(*self.take::<8>()?))
}
#[inline]
pub fn read_u64(&mut self) -> Result<u64, DecodeError> {
Ok(u64::from_le_bytes(*self.take::<8>()?))
}
#[inline]
pub fn read_f32(&mut self) -> Result<f32, DecodeError> {
Ok(f32::from_bits(self.read_u32()?))
}
#[inline]
pub fn read_f64(&mut self) -> Result<f64, DecodeError> {
Ok(f64::from_bits(self.read_u64()?))
}
pub fn read_string(&mut self) -> Result<String, DecodeError> {
let start = self.pos;
let len = self.read_prefixed_len(self.limits.max_string_len)?;
let bytes = self.take_slice(len).inspect_err(|_| self.pos = start)?;
match core::str::from_utf8(bytes) {
Ok(text) => Ok(text.to_owned()),
Err(_) => {
self.pos = start;
Err(DecodeError::InvalidUtf8)
}
}
}
pub fn read_bytes(&mut self) -> Result<Vec<u8>, DecodeError> {
let start = self.pos;
let len = self.read_prefixed_len(self.limits.max_bytes_len)?;
let bytes = self.take_slice(len).inspect_err(|_| self.pos = start)?;
Ok(bytes.to_vec())
}
pub fn read_array_count(&mut self) -> Result<usize, DecodeError> {
let start = self.pos;
let count = self.read_u32()? as usize;
if count > self.limits.max_array_count {
self.pos = start;
return Err(DecodeError::LengthOverflow {
length: count,
limit: self.limits.max_array_count,
});
}
Ok(count)
}
#[inline]
fn read_prefixed_len(&mut self, limit: usize) -> Result<usize, DecodeError> {
let start = self.pos;
let len = self.read_u32()? as usize;
if len > limit {
self.pos = start;
return Err(DecodeError::LengthOverflow { length: len, limit });
}
Ok(len)
}
#[inline]
fn take<const N: usize>(&mut self) -> Result<&'a [u8; N], DecodeError> {
let bytes = self.take_slice(N)?;
Ok(bytes.try_into().expect("slice length checked above"))
}
#[inline]
fn take_slice(&mut self, len: usize) -> Result<&'a [u8], DecodeError> {
let remaining = self.remaining();
if len > remaining {
return Err(DecodeError::UnexpectedEof { needed: len, remaining });
}
let bytes = &self.buf[self.pos..self.pos + len];
self.pos += len;
Ok(bytes)
}
}