#[cfg(not(feature = "permissive"))]
use super::limits::*;
use crate::serialize::reader::*;
pub struct BufReader<'r> {
data: &'r [u8],
pos: usize,
}
impl<'a> BufReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
let pos = 0;
Self { data, pos }
}
pub fn position(&self) -> usize {
self.pos
}
pub fn remaining(&self) -> usize {
self.data.len() - self.pos
}
pub fn remaining_slice(&self) -> &'a [u8] {
&self.data[self.pos..]
}
#[inline]
fn get_input(&mut self, requested: u32) -> ReadResult<&'a [u8]> {
let requested = requested as usize;
let remaining = self.data.len() - self.pos;
if requested > remaining {
#[cfg(all(target_arch = "riscv32", target_os = "none"))]
core::hint::cold_path();
return Err(ReadError::source_empty(requested, remaining));
}
let extent = self.pos + requested;
let buf = unsafe { self.data.get_unchecked(self.pos..extent) };
self.pos = extent;
Ok(buf)
}
#[inline]
fn read_byte(&mut self) -> ReadResult<u8> {
let byte = self.get_input(1)?;
Ok(unsafe { *byte.get_unchecked(0) })
}
#[cfg_attr(
any(
target_family = "wasm",
all(target_arch = "riscv32", target_os = "none"),
),
inline(never)
)]
#[cfg_attr(
not(any(
target_family = "wasm",
all(target_arch = "riscv32", target_os = "none"),
)),
inline(always)
)]
fn read_signed(&mut self) -> ReadResult<i64> {
let h = self.read_byte()?;
let s = (h & 0xc0) >> 6;
let v = h & !0xc0;
let n: i64;
if v == 63 {
n = match s {
0 => self.read_byte()? as i8 as i64,
1 => i16::from_le(unsafe {
core::ptr::read_unaligned(self.get_input(2)?.as_ptr().cast::<i16>())
}) as i64,
2 => i32::from_le(unsafe {
core::ptr::read_unaligned(self.get_input(4)?.as_ptr().cast::<i32>())
}) as i64,
3 => i64::from_le(unsafe {
core::ptr::read_unaligned(self.get_input(8)?.as_ptr().cast::<i64>())
}),
_ => unreachable!(),
};
#[cfg(not(feature = "permissive"))]
{
const N_BYTE_REPR_MINMAX: [(i64, i64); 4] = [
(IH_MAX as i64 + 1, IH_MIN as i64 - 1),
(i8::MAX as i64 + 1, i8::MIN as i64 - 1),
(i16::MAX as i64 + 1, i16::MIN as i64 - 1),
(i32::MAX as i64 + 1, i32::MIN as i64 - 1),
];
let (repr_min, repr_max) = N_BYTE_REPR_MINMAX[s as usize];
if n > 0 {
if n < repr_min {
return Err(ReadError::not_minimal_encoding());
}
} else if n > repr_max {
return Err(ReadError::not_minimal_encoding());
}
}
} else {
if s != 0 {
return Err(ReadError::invalid_header_byte(h));
}
if v & 0b10_0000 != 0 {
n = -(((!v) & 0b11_1111) as i64);
} else {
n = v as i64;
}
}
Ok(n)
}
#[cfg_attr(
any(
target_family = "wasm",
all(target_arch = "riscv32", target_os = "none"),
),
inline(never)
)]
#[cfg_attr(
not(any(
target_family = "wasm",
all(target_arch = "riscv32", target_os = "none"),
)),
inline(always)
)]
fn read_unsigned(&mut self) -> ReadResult<u64> {
let h = self.read_byte()?;
let s = (h & 0xc0) >> 6;
let v = h & !0xc0;
if v == 63 {
let uint = match s {
0 => self.read_byte()? as u64,
1 => u16::from_le(unsafe {
core::ptr::read_unaligned(self.get_input(2)?.as_ptr().cast::<u16>())
}) as u64,
2 => u32::from_le(unsafe {
core::ptr::read_unaligned(self.get_input(4)?.as_ptr().cast::<u32>())
}) as u64,
3 => u64::from_le(unsafe {
core::ptr::read_unaligned(self.get_input(8)?.as_ptr().cast::<u64>())
}),
_ => unreachable!(),
};
#[cfg(not(feature = "permissive"))]
{
const N_BYTE_REPR_MIN: [u64; 4] = [
63,
u8::MAX as u64 + 1,
u16::MAX as u64 + 1,
u32::MAX as u64 + 1,
];
let repr_min = N_BYTE_REPR_MIN[s as usize];
if uint < repr_min {
return Err(ReadError::not_minimal_encoding());
}
}
Ok(uint)
} else {
if s != 0 {
return Err(ReadError::invalid_header_byte(h));
}
Ok(v as u64)
}
}
}
macro_rules! read_signed {
{ $( [$f:ident, $ty:ty] ),* $(,)? } => { $(
#[inline]
fn $f(&mut self) -> ReadResult<$ty> {
let n = self.read_signed()?;
let n = n
.try_into()
.map_err(|_| ReadError::integer_out_of_range())?;
Ok(n)
}
)* };
}
macro_rules! read_unsigned {
{ $( [$f:ident, $ty:ty] ),* $(,)? } => { $(
#[inline]
fn $f(&mut self) -> ReadResult<$ty> {
let n = self.read_unsigned()?;
let n = n
.try_into()
.map_err(|_| ReadError::integer_out_of_range())?;
Ok(n)
}
)* };
}
unsafe impl<'r> Reader<'r> for BufReader<'r> {
read_signed! {
[read_i64, i64],
[read_i32, i32],
[read_i16, i16],
}
read_unsigned! {
[read_u64, u64],
[read_u32, u32],
[read_u16, u16],
}
#[inline]
fn read_f32(&mut self) -> ReadResult<f32> {
let input = self.read_opaque_fixed(4)?;
let mut bytes = [0u8; 4];
unsafe { core::ptr::copy_nonoverlapping(input.as_ptr(), bytes.as_mut_ptr(), 4) };
Ok(f32::from_le_bytes(bytes))
}
#[inline]
fn read_f64(&mut self) -> ReadResult<f64> {
let input = self.read_opaque_fixed(8)?;
let mut bytes = [0u8; 8];
unsafe { core::ptr::copy_nonoverlapping(input.as_ptr(), bytes.as_mut_ptr(), 8) };
Ok(f64::from_le_bytes(bytes))
}
#[inline]
fn read_opaque_fixed(&mut self, len: usize) -> ReadResult<&'r [u8]> {
debug_assert!(len <= u32::MAX as usize);
self.get_input(len as u32)
}
#[inline(always)]
fn read_opaque_variable(&mut self, max: u32) -> ReadResult<&'r [u8]> {
let len = self.read_u32()?;
if len > max {
return Err(ReadError::max_length_exceeded());
}
self.read_opaque_fixed(len as usize)
}
}