use core::hint::cold_path;
#[cfg(feature = "std")]
use alloc::vec;
use crate::Error;
use crate::FromCbor;
use crate::Result;
use crate::consts::*;
use crate::write::decode_f16;
#[cold]
#[inline(never)]
fn buffer_too_small<T>() -> Result<T> {
Err(Error::BufferTooSmall)
}
#[cold]
#[inline(never)]
fn invalid_initial_byte<T>(byte: u8) -> Result<T> {
Err(Error::InvalidInitialByte(byte))
}
pub const MAX_DEPTH: usize = 128;
fn validate_utf8(bytes: alloc::borrow::Cow<'_, [u8]>) -> Result<alloc::borrow::Cow<'_, str>> {
match bytes {
alloc::borrow::Cow::Borrowed(bytes) => match core::str::from_utf8(bytes) {
Ok(string) => Ok(alloc::borrow::Cow::Borrowed(string)),
Err(error) => {
cold_path();
Err(Error::InvalidUtf8(error))
}
},
alloc::borrow::Cow::Owned(bytes) => match alloc::string::String::from_utf8(bytes) {
Ok(string) => Ok(alloc::borrow::Cow::Owned(string)),
Err(error) => {
cold_path();
Err(Error::InvalidUtf8(error.utf8_error()))
}
},
}
}
const ARRAY_GROWTH: usize = 8;
const MAX_PREALLOC: usize = 1024;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Len {
Known(usize),
Indefinite,
}
impl Len {
#[inline(always)]
pub const fn known(self) -> Option<usize> {
match self {
Len::Known(len) => Some(len),
Len::Indefinite => None,
}
}
#[inline(always)]
pub const fn is_indefinite(self) -> bool {
matches!(self, Len::Indefinite)
}
}
#[derive(Debug, Clone)]
pub struct ArrayIter {
len: Len,
index: usize,
}
impl ArrayIter {
#[inline(always)]
pub fn next<'de, R: Read<'de> + ?Sized>(&mut self, reader: &mut R) -> Result<bool> {
match reader.next_element(self.len, &mut self.index) {
Ok(true) => Ok(true),
Ok(false) => {
reader.decrement_depth();
Ok(false)
}
Err(error) => {
reader.decrement_depth();
Err(error)
}
}
}
#[inline(always)]
pub const fn header(&self) -> Len {
self.len
}
#[inline(always)]
pub const fn is_indefinite(&self) -> bool {
self.len.is_indefinite()
}
}
#[derive(Debug, Clone)]
pub struct MapIter {
len: Len,
index: usize,
}
impl MapIter {
#[inline(always)]
pub fn next<'de, R: Read<'de> + ?Sized>(&mut self, reader: &mut R) -> Result<bool> {
match reader.next_element(self.len, &mut self.index) {
Ok(true) => Ok(true),
Ok(false) => {
reader.decrement_depth();
Ok(false)
}
Err(error) => {
reader.decrement_depth();
Err(error)
}
}
}
#[inline(always)]
pub const fn header(&self) -> Len {
self.len
}
#[inline(always)]
pub const fn is_indefinite(&self) -> bool {
self.len.is_indefinite()
}
}
pub trait Read<'de> {
fn peek_initial_byte(&mut self) -> Result<u8>;
fn increment_depth(&mut self) -> Result<()>;
fn decrement_depth(&mut self);
fn read_null(&mut self) -> Result<()>;
fn read_boolean(&mut self) -> Result<bool>;
fn read_u8(&mut self) -> Result<u8>;
fn read_u16(&mut self) -> Result<u16>;
fn read_u32(&mut self) -> Result<u32>;
fn read_u64(&mut self) -> Result<u64>;
fn read_i8(&mut self) -> Result<i8>;
fn read_i16(&mut self) -> Result<i16>;
fn read_i32(&mut self) -> Result<i32>;
fn read_i64(&mut self) -> Result<i64>;
fn read_integer(&mut self) -> Result<i128>;
fn read_f16(&mut self) -> Result<f32>;
fn read_f32(&mut self) -> Result<f32>;
fn read_f64(&mut self) -> Result<f64>;
fn read_array_len(&mut self) -> Result<Len>;
fn read_map_len(&mut self) -> Result<Len>;
fn read_tag(&mut self) -> Result<u64>;
#[inline(always)]
fn check_tag(&mut self, expected: u64) -> Result<()> {
let byte = self.peek_initial_byte()?;
if byte & MAJOR_TYPE_MASK != MAJOR_TYPE_TAG {
cold_path();
return Err(Error::TagMismatch {
expected,
found: None,
});
}
let found = self.read_tag()?;
if found == expected {
Ok(())
} else {
cold_path();
Err(Error::TagMismatch {
expected,
found: Some(found),
})
}
}
fn read_simple_value(&mut self) -> Result<u8>;
fn read_undefined(&mut self) -> Result<()>;
fn read_string(&mut self) -> Result<alloc::borrow::Cow<'de, str>>;
fn read_string_bytes(&mut self) -> Result<alloc::borrow::Cow<'de, [u8]>>;
fn read_binary(&mut self) -> Result<alloc::borrow::Cow<'de, [u8]>>;
#[inline(always)]
fn at_map(&mut self) -> Result<bool> {
Ok(self.peek_initial_byte()? & MAJOR_TYPE_MASK == MAJOR_TYPE_MAP)
}
#[inline(always)]
fn at_tag(&mut self) -> Result<bool> {
Ok(self.peek_initial_byte()? & MAJOR_TYPE_MASK == MAJOR_TYPE_TAG)
}
fn read_break(&mut self) -> Result<()>;
fn read_chunk(&mut self, major: u8) -> Result<Option<(Len, alloc::borrow::Cow<'de, [u8]>)>>;
fn read_option<T: FromCbor<'de>>(&mut self) -> Result<Option<T>>;
#[inline(always)]
fn read_array<T: FromCbor<'de>>(&mut self, out: &mut alloc::vec::Vec<T>) -> Result<()>
where
Self: Sized,
{
out.clear();
let len = self.read_array_len()?;
if let Len::Known(count) = len
&& count <= MAX_PREALLOC
{
out.reserve(count);
}
self.increment_depth()?;
let result = (|| -> Result<()> {
match len {
Len::Known(count) => {
for _ in 0..count {
out.push(T::read(self)?);
}
}
Len::Indefinite => {
let mut index = 0;
while self.next_element(len, &mut index)? {
out.push(T::read(self)?);
}
}
}
self.finish_array(len)?;
Ok(())
})();
self.decrement_depth();
if result.is_err() {
out.clear();
}
result
}
#[inline(always)]
fn check_array_len(&mut self, expected: usize) -> Result<Len> {
let actual = self.read_array_len()?;
match actual {
Len::Indefinite => Ok(actual),
Len::Known(found) if found == expected => Ok(actual),
Len::Known(found) => {
cold_path();
Err(Error::ArrayLengthMismatch {
expected,
actual: found,
})
}
}
}
#[inline(always)]
fn check_map_len(&mut self, expected: usize) -> Result<Len> {
let actual = self.read_map_len()?;
match actual {
Len::Indefinite => Ok(actual),
Len::Known(found) if found == expected => Ok(actual),
Len::Known(found) => {
cold_path();
Err(Error::MapLengthMismatch {
expected,
actual: found,
})
}
}
}
#[inline(always)]
fn finish_array(&mut self, len: Len) -> Result<()> {
match len {
Len::Known(_) => Ok(()),
Len::Indefinite => self.read_break(),
}
}
#[inline(always)]
fn finish_map(&mut self, len: Len) -> Result<()> {
match len {
Len::Known(_) => Ok(()),
Len::Indefinite => self.read_break(),
}
}
#[inline(always)]
fn next_element(&mut self, len: Len, index: &mut usize) -> Result<bool> {
match len {
Len::Known(count) => {
if *index < count {
*index += 1;
Ok(true)
} else {
Ok(false)
}
}
Len::Indefinite => {
let at_break = self.at_break()?;
Ok(!at_break)
}
}
}
#[inline(always)]
fn at_break(&mut self) -> Result<bool> {
Ok(self.peek_initial_byte()? == BREAK)
}
#[inline(always)]
fn array_iter(&mut self) -> Result<ArrayIter>
where
Self: Sized,
{
self.array_iter_from(None)
}
#[inline(always)]
fn array_iter_from(&mut self, len: Option<Len>) -> Result<ArrayIter>
where
Self: Sized,
{
let len = match len {
Some(len) => len,
None => self.read_array_len()?,
};
self.increment_depth()?;
Ok(ArrayIter { len, index: 0 })
}
#[inline(always)]
fn map_iter(&mut self) -> Result<MapIter>
where
Self: Sized,
{
self.map_iter_from(None)
}
#[inline(always)]
fn map_iter_from(&mut self, len: Option<Len>) -> Result<MapIter>
where
Self: Sized,
{
let len = match len {
Some(len) => len,
None => self.read_map_len()?,
};
self.increment_depth()?;
Ok(MapIter { len, index: 0 })
}
fn read_signed(&mut self) -> Result<i64>;
fn skip_value(&mut self) -> Result<()>;
}
pub(crate) struct SliceReader<'de> {
data: &'de [u8],
pos: usize,
depth: usize,
}
impl<'de> SliceReader<'de> {
pub fn new(data: &'de [u8]) -> Self {
Self {
data,
pos: 0,
depth: 0,
}
}
#[inline(always)]
fn peek_byte(&mut self) -> Result<u8> {
if self.pos < self.data.len() {
unsafe { Ok(*self.data.get_unchecked(self.pos)) }
} else {
cold_path();
buffer_too_small()
}
}
#[inline(always)]
fn peek_slice(&mut self, len: usize) -> Result<&'de [u8]> {
if len <= self.data.len() - self.pos {
unsafe { Ok(self.data.get_unchecked(self.pos..(self.pos + len))) }
} else {
cold_path();
buffer_too_small()
}
}
#[inline(always)]
fn take_byte(&mut self) -> Result<u8> {
if self.pos < self.data.len() {
let byte = unsafe { *self.data.get_unchecked(self.pos) };
self.pos += 1;
Ok(byte)
} else {
cold_path();
buffer_too_small()
}
}
#[inline(always)]
fn take_slice(&mut self, len: usize) -> Result<&'de [u8]> {
let slice = self.peek_slice(len)?;
self.pos += len;
Ok(slice)
}
#[inline(always)]
fn take_array_from(&mut self, len: usize) -> Option<&'de [u8]> {
let remaining = self.data.len().checked_sub(self.pos)?;
if len <= remaining {
let slice = &self.data[self.pos..self.pos + len];
self.pos += len;
Some(slice)
} else {
None
}
}
#[inline(always)]
fn take_array<const N: usize>(&mut self) -> Result<&'de [u8; N]> {
if N <= self.data.len() - self.pos {
let array = unsafe { &*(self.data.as_ptr().add(self.pos) as *const [u8; N]) };
self.pos += N;
Ok(array)
} else {
cold_path();
buffer_too_small()
}
}
#[inline(always)]
fn read_additional_info(&mut self, byte: u8) -> Result<u64> {
let info = byte & !MAJOR_TYPE_MASK;
match info {
0..=23 => Ok(info as u64),
ADDITIONAL_INFO_1_BYTE => {
let val = self.take_byte()? as u64;
Ok(val)
}
ADDITIONAL_INFO_2_BYTES => {
let bytes = self.take_array::<2>()?;
Ok(u16::from_be_bytes(*bytes) as u64)
}
ADDITIONAL_INFO_4_BYTES => {
let bytes = self.take_array::<4>()?;
Ok(u32::from_be_bytes(*bytes) as u64)
}
ADDITIONAL_INFO_8_BYTES => {
let bytes = self.take_array::<8>()?;
Ok(u64::from_be_bytes(*bytes))
}
ADDITIONAL_INFO_INDEFINITE => {
cold_path();
Err(Error::InvalidAdditionalInfo(ADDITIONAL_INFO_INDEFINITE))
}
_ => {
cold_path();
Err(Error::InvalidInitialByte(byte))
}
}
}
#[inline(always)]
fn skip_array_values(&mut self, len: usize) -> Result<()> {
self.increment_depth()?;
let result = (0..len).try_for_each(|_| self.skip_value());
self.decrement_depth();
result
}
#[inline(always)]
fn skip_map_entries(&mut self, len: usize) -> Result<()> {
self.increment_depth()?;
let result = (0..len).try_for_each(|_| {
self.skip_value()?;
self.skip_value()
});
self.decrement_depth();
result
}
#[inline(always)]
fn skip_array_until_break(&mut self) -> Result<()> {
self.increment_depth()?;
let result = (|| -> Result<()> {
while !self.at_break()? {
self.skip_value()?;
}
self.read_break()
})();
self.decrement_depth();
result
}
#[inline(always)]
fn skip_map_until_break(&mut self) -> Result<()> {
self.increment_depth()?;
let result = (|| -> Result<()> {
while !self.at_break()? {
self.skip_value()?;
self.skip_value()?;
}
self.read_break()
})();
self.decrement_depth();
result
}
#[inline(always)]
fn skip_chunks(&mut self, major: u8) -> Result<()> {
while self.read_chunk(major)?.is_some() {}
Ok(())
}
#[inline(always)]
fn read_string_head(&mut self, byte: u8) -> Result<alloc::borrow::Cow<'de, [u8]>> {
match self.read_additional_info(byte) {
Ok(len) => Ok(alloc::borrow::Cow::Borrowed(self.take_slice(
usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?,
)?)),
Err(Error::InvalidAdditionalInfo(_)) => {
self.read_chunked(crate::consts::MAJOR_TYPE_TEXT_STRING)
}
Err(error) => Err(error),
}
}
#[inline(always)]
fn read_binary_head(&mut self, byte: u8) -> Result<alloc::borrow::Cow<'de, [u8]>> {
match self.read_additional_info(byte) {
Ok(len) => Ok(alloc::borrow::Cow::Borrowed(self.take_slice(
usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?,
)?)),
Err(Error::InvalidAdditionalInfo(_)) => {
self.read_chunked(crate::consts::MAJOR_TYPE_BYTE_STRING)
}
Err(error) => Err(error),
}
}
#[cold]
#[inline(never)]
fn read_chunked(&mut self, major: u8) -> Result<alloc::borrow::Cow<'de, [u8]>> {
let first = match self.read_chunk(major)? {
Some((_, bytes)) => bytes,
None => return Ok(alloc::borrow::Cow::Owned(alloc::vec::Vec::new())),
};
if self.at_break()? {
self.read_break()?;
return Ok(first);
}
let mut out = match first {
alloc::borrow::Cow::Borrowed(bytes) => bytes.to_vec(),
alloc::borrow::Cow::Owned(bytes) => bytes,
};
while let Some((_, chunk)) = self.read_chunk(major)? {
out.extend_from_slice(&chunk);
}
Ok(alloc::borrow::Cow::Owned(out))
}
}
impl<'de> Read<'de> for SliceReader<'de> {
#[inline(always)]
fn peek_initial_byte(&mut self) -> Result<u8> {
self.peek_byte()
}
#[inline(always)]
fn increment_depth(&mut self) -> Result<()> {
if self.depth >= MAX_DEPTH {
cold_path();
Err(Error::DepthLimitExceeded)
} else {
self.depth += 1;
Ok(())
}
}
#[inline(always)]
fn decrement_depth(&mut self) {
if self.depth > 0 {
self.depth -= 1;
} else {
cold_path();
}
}
#[inline(always)]
fn read_null(&mut self) -> Result<()> {
let byte = self.take_byte()?;
if byte == SIMPLE_VALUE_NULL {
Ok(())
} else {
cold_path();
invalid_initial_byte(byte)
}
}
#[inline(always)]
fn read_boolean(&mut self) -> Result<bool> {
let byte = self.take_byte()?;
match byte {
SIMPLE_VALUE_TRUE => Ok(true),
SIMPLE_VALUE_FALSE => Ok(false),
_ => {
cold_path();
invalid_initial_byte(byte)
}
}
}
#[inline(always)]
fn read_simple_value(&mut self) -> Result<u8> {
let byte = self.take_byte()?;
match byte & !MAJOR_TYPE_MASK {
0..=23 => Ok(byte & !MAJOR_TYPE_MASK),
ADDITIONAL_INFO_1_BYTE => {
let value = self.take_byte()?;
match value {
0..=31 => {
cold_path();
Err(Error::InvalidSimpleValue(value))
}
_ => Ok(value),
}
}
_ => {
cold_path();
Err(Error::InvalidSimpleValue(byte & !MAJOR_TYPE_MASK))
}
}
}
#[inline(always)]
fn read_undefined(&mut self) -> Result<()> {
let byte = self.take_byte()?;
if byte == SIMPLE_VALUE_UNDEFINED {
Ok(())
} else {
cold_path();
invalid_initial_byte(byte)
}
}
#[inline(always)]
fn read_u8(&mut self) -> Result<u8> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
let value = self.read_additional_info(byte)?;
if value > u8::MAX as u64 {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
Ok(value as u8)
}
#[inline(always)]
fn read_u16(&mut self) -> Result<u16> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
let value = self.read_additional_info(byte)?;
if value > u16::MAX as u64 {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
Ok(value as u16)
}
#[inline(always)]
fn read_u32(&mut self) -> Result<u32> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
let value = self.read_additional_info(byte)?;
if value > u32::MAX as u64 {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
Ok(value as u32)
}
#[inline(always)]
fn read_u64(&mut self) -> Result<u64> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
self.read_additional_info(byte)
}
#[inline(always)]
fn read_i8(&mut self) -> Result<i8> {
self.read_signed()
.and_then(|v| i8::try_from(v).map_err(|_| Error::IntegerOutOfRange))
}
#[inline(always)]
fn read_i16(&mut self) -> Result<i16> {
self.read_signed()
.and_then(|v| i16::try_from(v).map_err(|_| Error::IntegerOutOfRange))
}
#[inline(always)]
fn read_i32(&mut self) -> Result<i32> {
self.read_signed()
.and_then(|v| i32::try_from(v).map_err(|_| Error::IntegerOutOfRange))
}
fn read_integer(&mut self) -> Result<i128> {
let byte = self.take_byte()?;
let value = self.read_additional_info(byte)?;
match byte & MAJOR_TYPE_MASK {
MAJOR_TYPE_UNSIGNED_INT => Ok(value as i128),
MAJOR_TYPE_NEGATIVE_INT => Ok(-1i128 - value as i128),
_ => {
cold_path();
invalid_initial_byte(byte)
}
}
}
#[inline(always)]
fn read_i64(&mut self) -> Result<i64> {
self.read_signed()
}
#[inline(always)]
fn read_signed(&mut self) -> Result<i64> {
let byte = self.take_byte()?;
let value = self.read_additional_info(byte)?;
match byte & MAJOR_TYPE_MASK {
MAJOR_TYPE_UNSIGNED_INT => {
i64::try_from(value).map_err(|_| Error::IntegerOutOfRange)
}
MAJOR_TYPE_NEGATIVE_INT => {
i64::try_from(-1i128 - value as i128).map_err(|_| Error::IntegerOutOfRange)
}
_ => {
cold_path();
invalid_initial_byte(byte)
}
}
}
#[inline(always)]
fn read_f16(&mut self) -> Result<f32> {
let byte = self.take_byte()?;
if byte != FLOAT16_MARKER {
cold_path();
return invalid_initial_byte(byte);
}
let bytes = self.take_array::<2>()?;
let bits = u16::from_be_bytes(*bytes);
Ok(decode_f16(bits))
}
#[inline(always)]
fn read_f32(&mut self) -> Result<f32> {
let byte = self.take_byte()?;
if byte != FLOAT32_MARKER {
cold_path();
return invalid_initial_byte(byte);
}
let bytes = self.take_array::<4>()?;
Ok(f32::from_be_bytes(*bytes))
}
#[inline(always)]
fn read_f64(&mut self) -> Result<f64> {
let byte = self.take_byte()?;
if byte != FLOAT64_MARKER {
cold_path();
return invalid_initial_byte(byte);
}
let bytes = self.take_array::<8>()?;
Ok(f64::from_be_bytes(*bytes))
}
#[inline(always)]
fn read_chunk(&mut self, major: u8) -> Result<Option<(Len, alloc::borrow::Cow<'de, [u8]>)>> {
if self.at_break()? {
self.read_break()?;
return Ok(None);
}
let byte = self.take_byte()?;
if byte & MAJOR_TYPE_MASK != major {
cold_path();
return invalid_initial_byte(byte);
}
let len = usize::try_from(self.read_additional_info(byte)?)
.map_err(|_| Error::IntegerOutOfRange)?;
let bytes = match self.take_array_from(len) {
Some(array) => array,
None => return buffer_too_small(),
};
if major == MAJOR_TYPE_TEXT_STRING {
core::str::from_utf8(bytes).map_err(Error::InvalidUtf8)?;
}
Ok(Some((Len::Known(len), alloc::borrow::Cow::Borrowed(bytes))))
}
#[inline(always)]
fn read_break(&mut self) -> Result<()> {
let byte = self.take_byte()?;
if byte == BREAK {
Ok(())
} else {
cold_path();
invalid_initial_byte(byte)
}
}
#[inline(always)]
fn read_array_len(&mut self) -> Result<Len> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_ARRAY {
cold_path();
return invalid_initial_byte(byte);
}
Ok(match self.read_additional_info(byte) {
Ok(len) => Len::Known(usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?),
Err(Error::InvalidAdditionalInfo(_)) => Len::Indefinite,
Err(error) => return Err(error),
})
}
#[inline(always)]
fn read_map_len(&mut self) -> Result<Len> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_MAP {
cold_path();
return invalid_initial_byte(byte);
}
Ok(match self.read_additional_info(byte) {
Ok(len) => Len::Known(usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?),
Err(Error::InvalidAdditionalInfo(_)) => Len::Indefinite,
Err(error) => return Err(error),
})
}
#[inline(always)]
fn read_tag(&mut self) -> Result<u64> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_TAG {
cold_path();
return invalid_initial_byte(byte);
}
self.read_additional_info(byte)
}
#[inline(always)]
fn read_string(&mut self) -> Result<alloc::borrow::Cow<'de, str>> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_TEXT_STRING {
cold_path();
return invalid_initial_byte(byte);
}
validate_utf8(self.read_string_head(byte)?)
}
#[inline(always)]
fn read_string_bytes(&mut self) -> Result<alloc::borrow::Cow<'de, [u8]>> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_TEXT_STRING {
cold_path();
return invalid_initial_byte(byte);
}
self.read_string_head(byte)
}
#[inline(always)]
fn read_binary(&mut self) -> Result<alloc::borrow::Cow<'de, [u8]>> {
let byte = self.take_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_BYTE_STRING {
cold_path();
return invalid_initial_byte(byte);
}
self.read_binary_head(byte)
}
#[inline(always)]
fn read_option<T: FromCbor<'de>>(&mut self) -> Result<Option<T>> {
let byte = self.peek_byte()?;
if byte == SIMPLE_VALUE_NULL {
self.pos += 1;
Ok(None)
} else {
Ok(Some(T::read(self)?))
}
}
#[inline(always)]
fn read_array<T: FromCbor<'de>>(&mut self, out: &mut alloc::vec::Vec<T>) -> Result<()> {
out.clear();
let len = self.read_array_len()?;
if let Len::Known(count) = len
&& self.data.len() - self.pos < count
{
cold_path();
return Err(Error::BufferTooSmall);
}
if let Len::Known(count) = len
&& out.capacity() < count
{
out.reserve(count);
}
self.increment_depth()?;
let result = (|| -> Result<()> {
let mut index = 0;
let mut initialized = 0usize;
while self.next_element(len, &mut index)? {
let value = T::read(self)?;
if initialized == out.capacity() {
out.reserve(initialized.max(ARRAY_GROWTH));
}
unsafe {
out.as_mut_ptr().add(initialized).write(value);
out.set_len(initialized + 1);
}
initialized += 1;
}
self.finish_array(len)
})();
self.decrement_depth();
if result.is_err() {
out.clear();
}
result
}
fn skip_value(&mut self) -> Result<()> {
let byte = self.peek_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
let info = byte & !MAJOR_TYPE_MASK;
match major_type {
MAJOR_TYPE_UNSIGNED_INT | MAJOR_TYPE_NEGATIVE_INT | MAJOR_TYPE_TAG => {
self.pos += 1;
self.skip_additional_info(info)?;
}
MAJOR_TYPE_BYTE_STRING | MAJOR_TYPE_TEXT_STRING => {
self.pos += 1;
if info == ADDITIONAL_INFO_INDEFINITE {
self.skip_chunks(major_type)?;
} else {
let len = usize::try_from(self.skip_additional_info(info)?)
.map_err(|_| Error::IntegerOutOfRange)?;
self.take_slice(len)?;
}
}
MAJOR_TYPE_ARRAY => {
self.pos += 1;
if info == ADDITIONAL_INFO_INDEFINITE {
self.skip_array_until_break()?;
} else {
let len = usize::try_from(self.skip_additional_info(info)?)
.map_err(|_| Error::IntegerOutOfRange)?;
self.skip_array_values(len)?;
}
}
MAJOR_TYPE_MAP => {
self.pos += 1;
if info == ADDITIONAL_INFO_INDEFINITE {
self.skip_map_until_break()?;
} else {
let len = usize::try_from(self.skip_additional_info(info)?)
.map_err(|_| Error::IntegerOutOfRange)?;
self.skip_map_entries(len)?;
}
}
MAJOR_TYPE_SIMPLE_FLOAT => match info {
0..=23 | 31 => {
self.pos += 1;
}
ADDITIONAL_INFO_1_BYTE => {
self.take_slice(2)?;
}
ADDITIONAL_INFO_2_BYTES => {
self.take_slice(3)?;
}
ADDITIONAL_INFO_4_BYTES => {
self.take_slice(5)?;
}
ADDITIONAL_INFO_8_BYTES => {
self.take_slice(9)?;
}
_ => {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
},
_ => {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
}
Ok(())
}
}
impl<'de> SliceReader<'de> {
#[inline(always)]
fn skip_additional_info(&mut self, info: u8) -> Result<u64> {
match info {
0..=23 => Ok(info as u64),
ADDITIONAL_INFO_1_BYTE => {
let val = self.take_byte()? as u64;
Ok(val)
}
ADDITIONAL_INFO_2_BYTES => {
let bytes = self.take_array::<2>()?;
Ok(u16::from_be_bytes(*bytes) as u64)
}
ADDITIONAL_INFO_4_BYTES => {
let bytes = self.take_array::<4>()?;
Ok(u32::from_be_bytes(*bytes) as u64)
}
ADDITIONAL_INFO_8_BYTES => {
let bytes = self.take_array::<8>()?;
Ok(u64::from_be_bytes(*bytes))
}
ADDITIONAL_INFO_INDEFINITE => {
cold_path();
Err(Error::InvalidAdditionalInfo(ADDITIONAL_INFO_INDEFINITE))
}
_ => {
cold_path();
Err(Error::InvalidInitialByte(info))
}
}
}
}
#[cfg(feature = "std")]
pub(crate) struct IOReader<R: std::io::Read> {
reader: R,
depth: usize,
peeked: Option<u8>,
}
#[cfg(feature = "std")]
impl<R: std::io::Read> IOReader<R> {
#[inline(always)]
fn read_string_head(&mut self, byte: u8) -> Result<alloc::vec::Vec<u8>> {
match self.read_additional_info(byte) {
Ok(len) => {
self.read_exact_vec(usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?)
}
Err(Error::InvalidAdditionalInfo(_)) => {
self.read_chunked(crate::consts::MAJOR_TYPE_TEXT_STRING)
}
Err(error) => Err(error),
}
}
#[inline(always)]
fn read_binary_head(&mut self, byte: u8) -> Result<alloc::vec::Vec<u8>> {
match self.read_additional_info(byte) {
Ok(len) => {
self.read_exact_vec(usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?)
}
Err(Error::InvalidAdditionalInfo(_)) => {
self.read_chunked(crate::consts::MAJOR_TYPE_BYTE_STRING)
}
Err(error) => Err(error),
}
}
#[cold]
#[inline(never)]
fn read_chunked(&mut self, major: u8) -> Result<alloc::vec::Vec<u8>> {
let mut out = alloc::vec::Vec::new();
while let Some((_, chunk)) = self.read_chunk(major)? {
out.extend_from_slice(&chunk);
}
Ok(out)
}
pub fn new(reader: R) -> Self {
Self {
reader,
depth: 0,
peeked: None,
}
}
#[inline(always)]
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
self.reader.read_exact(buf).map_err(Error::IoError)
}
#[inline(always)]
fn read_byte(&mut self) -> Result<u8> {
if let Some(byte) = self.peeked.take() {
Ok(byte)
} else {
let mut buf = [0u8; 1];
self.read_exact(&mut buf)?;
Ok(buf[0])
}
}
#[inline(always)]
fn read_exact_vec(&mut self, len: usize) -> Result<alloc::vec::Vec<u8>> {
const CHUNK_SIZE: usize = 8192;
if len == 0 {
return Ok(alloc::vec::Vec::new());
} else if len < CHUNK_SIZE {
let mut buf = vec![0u8; len];
self.reader.read_exact(&mut buf).map_err(Error::IoError)?;
return Ok(buf);
}
let mut out = alloc::vec::Vec::new();
self.read_exact_into(len, &mut out)?;
Ok(out)
}
#[inline(always)]
fn read_additional_info(&mut self, byte: u8) -> Result<u64> {
let info = byte & !MAJOR_TYPE_MASK;
match info {
0..=23 => Ok(info as u64),
ADDITIONAL_INFO_1_BYTE => {
let val = self.read_byte()? as u64;
Ok(val)
}
ADDITIONAL_INFO_2_BYTES => {
let mut bytes = [0; 2];
self.read_exact(&mut bytes)?;
Ok(u16::from_be_bytes(bytes) as u64)
}
ADDITIONAL_INFO_4_BYTES => {
let mut bytes = [0; 4];
self.read_exact(&mut bytes)?;
Ok(u32::from_be_bytes(bytes) as u64)
}
ADDITIONAL_INFO_8_BYTES => {
let mut bytes = [0; 8];
self.read_exact(&mut bytes)?;
Ok(u64::from_be_bytes(bytes))
}
ADDITIONAL_INFO_INDEFINITE => {
cold_path();
Err(Error::InvalidAdditionalInfo(ADDITIONAL_INFO_INDEFINITE))
}
_ => {
cold_path();
Err(Error::InvalidInitialByte(byte))
}
}
}
}
#[cfg(feature = "std")]
impl<'de, R: std::io::Read> Read<'de> for IOReader<R> {
#[inline(always)]
fn peek_initial_byte(&mut self) -> Result<u8> {
if let Some(byte) = self.peeked {
Ok(byte)
} else {
let byte = self.read_byte()?;
self.peeked = Some(byte);
Ok(byte)
}
}
#[inline(always)]
fn increment_depth(&mut self) -> Result<()> {
if self.depth >= MAX_DEPTH {
cold_path();
Err(Error::DepthLimitExceeded)
} else {
self.depth += 1;
Ok(())
}
}
#[inline(always)]
fn decrement_depth(&mut self) {
if self.depth > 0 {
self.depth -= 1;
} else {
cold_path();
}
}
#[inline(always)]
fn read_null(&mut self) -> Result<()> {
let byte = self.read_byte()?;
if byte == SIMPLE_VALUE_NULL {
Ok(())
} else {
cold_path();
invalid_initial_byte(byte)
}
}
#[inline(always)]
fn read_boolean(&mut self) -> Result<bool> {
let byte = self.read_byte()?;
match byte {
SIMPLE_VALUE_TRUE => Ok(true),
SIMPLE_VALUE_FALSE => Ok(false),
_ => {
cold_path();
invalid_initial_byte(byte)
}
}
}
#[inline(always)]
fn read_simple_value(&mut self) -> Result<u8> {
let byte = self.read_byte()?;
match byte & !MAJOR_TYPE_MASK {
0..=23 => Ok(byte & !MAJOR_TYPE_MASK),
ADDITIONAL_INFO_1_BYTE => {
let value = self.read_byte()?;
match value {
0..=31 => {
cold_path();
Err(Error::InvalidSimpleValue(value))
}
_ => Ok(value),
}
}
_ => {
cold_path();
Err(Error::InvalidSimpleValue(byte & !MAJOR_TYPE_MASK))
}
}
}
#[inline(always)]
fn read_undefined(&mut self) -> Result<()> {
let byte = self.read_byte()?;
if byte == SIMPLE_VALUE_UNDEFINED {
Ok(())
} else {
cold_path();
invalid_initial_byte(byte)
}
}
#[inline(always)]
fn read_u8(&mut self) -> Result<u8> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
let value = self.read_additional_info(byte)?;
if value > u8::MAX as u64 {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
Ok(value as u8)
}
#[inline(always)]
fn read_u16(&mut self) -> Result<u16> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
let value = self.read_additional_info(byte)?;
if value > u16::MAX as u64 {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
Ok(value as u16)
}
#[inline(always)]
fn read_u32(&mut self) -> Result<u32> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
let value = self.read_additional_info(byte)?;
if value > u32::MAX as u64 {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
Ok(value as u32)
}
#[inline(always)]
fn read_u64(&mut self) -> Result<u64> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_UNSIGNED_INT {
cold_path();
return invalid_initial_byte(byte);
}
self.read_additional_info(byte)
}
#[inline(always)]
fn read_i8(&mut self) -> Result<i8> {
self.read_signed()
.and_then(|v| i8::try_from(v).map_err(|_| Error::IntegerOutOfRange))
}
#[inline(always)]
fn read_i16(&mut self) -> Result<i16> {
self.read_signed()
.and_then(|v| i16::try_from(v).map_err(|_| Error::IntegerOutOfRange))
}
#[inline(always)]
fn read_i32(&mut self) -> Result<i32> {
self.read_signed()
.and_then(|v| i32::try_from(v).map_err(|_| Error::IntegerOutOfRange))
}
fn read_integer(&mut self) -> Result<i128> {
let byte = self.read_byte()?;
let value = self.read_additional_info(byte)?;
match byte & MAJOR_TYPE_MASK {
MAJOR_TYPE_UNSIGNED_INT => Ok(value as i128),
MAJOR_TYPE_NEGATIVE_INT => Ok(-1i128 - value as i128),
_ => {
cold_path();
invalid_initial_byte(byte)
}
}
}
#[inline(always)]
fn read_i64(&mut self) -> Result<i64> {
self.read_signed()
}
#[inline(always)]
fn read_signed(&mut self) -> Result<i64> {
let byte = self.read_byte()?;
let value = self.read_additional_info(byte)?;
match byte & MAJOR_TYPE_MASK {
MAJOR_TYPE_UNSIGNED_INT => {
i64::try_from(value).map_err(|_| Error::IntegerOutOfRange)
}
MAJOR_TYPE_NEGATIVE_INT => {
i64::try_from(-1i128 - value as i128).map_err(|_| Error::IntegerOutOfRange)
}
_ => {
cold_path();
invalid_initial_byte(byte)
}
}
}
#[inline(always)]
fn read_f16(&mut self) -> Result<f32> {
let byte = self.read_byte()?;
if byte != FLOAT16_MARKER {
cold_path();
return invalid_initial_byte(byte);
}
let mut bytes = [0; 2];
self.read_exact(&mut bytes)?;
let bits = u16::from_be_bytes(bytes);
Ok(decode_f16(bits))
}
#[inline(always)]
fn read_f32(&mut self) -> Result<f32> {
let byte = self.read_byte()?;
if byte != FLOAT32_MARKER {
cold_path();
return invalid_initial_byte(byte);
}
let mut bytes = [0; 4];
self.read_exact(&mut bytes)?;
Ok(f32::from_be_bytes(bytes))
}
#[inline(always)]
fn read_f64(&mut self) -> Result<f64> {
let byte = self.read_byte()?;
if byte != FLOAT64_MARKER {
cold_path();
return invalid_initial_byte(byte);
}
let mut bytes = [0; 8];
self.read_exact(&mut bytes)?;
Ok(f64::from_be_bytes(bytes))
}
#[inline(always)]
fn read_chunk(&mut self, major: u8) -> Result<Option<(Len, alloc::borrow::Cow<'de, [u8]>)>> {
if self.at_break()? {
self.read_break()?;
return Ok(None);
}
let byte = self.read_byte()?;
if byte & MAJOR_TYPE_MASK != major {
cold_path();
return invalid_initial_byte(byte);
}
let len = usize::try_from(self.read_additional_info(byte)?)
.map_err(|_| Error::IntegerOutOfRange)?;
let mut out = alloc::vec::Vec::new();
self.read_exact_into(len, &mut out)?;
if major == MAJOR_TYPE_TEXT_STRING {
core::str::from_utf8(&out).map_err(Error::InvalidUtf8)?;
}
Ok(Some((Len::Known(len), alloc::borrow::Cow::Owned(out))))
}
#[inline(always)]
fn read_break(&mut self) -> Result<()> {
let byte = self.read_byte()?;
if byte == BREAK {
Ok(())
} else {
cold_path();
invalid_initial_byte(byte)
}
}
#[inline(always)]
fn read_array_len(&mut self) -> Result<Len> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_ARRAY {
cold_path();
return invalid_initial_byte(byte);
}
Ok(match self.read_additional_info(byte) {
Ok(len) => Len::Known(usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?),
Err(Error::InvalidAdditionalInfo(_)) => Len::Indefinite,
Err(error) => return Err(error),
})
}
#[inline(always)]
fn read_map_len(&mut self) -> Result<Len> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_MAP {
cold_path();
return invalid_initial_byte(byte);
}
Ok(match self.read_additional_info(byte) {
Ok(len) => Len::Known(usize::try_from(len).map_err(|_| Error::IntegerOutOfRange)?),
Err(Error::InvalidAdditionalInfo(_)) => Len::Indefinite,
Err(error) => return Err(error),
})
}
#[inline(always)]
fn read_tag(&mut self) -> Result<u64> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_TAG {
cold_path();
return invalid_initial_byte(byte);
}
self.read_additional_info(byte)
}
#[inline(always)]
fn read_string(&mut self) -> Result<alloc::borrow::Cow<'de, str>> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_TEXT_STRING {
cold_path();
return invalid_initial_byte(byte);
}
validate_utf8(alloc::borrow::Cow::Owned(self.read_string_head(byte)?))
}
#[inline(always)]
fn read_string_bytes(&mut self) -> Result<alloc::borrow::Cow<'de, [u8]>> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_TEXT_STRING {
cold_path();
return invalid_initial_byte(byte);
}
Ok(alloc::borrow::Cow::Owned(self.read_string_head(byte)?))
}
#[inline(always)]
fn read_binary(&mut self) -> Result<alloc::borrow::Cow<'de, [u8]>> {
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
if major_type != MAJOR_TYPE_BYTE_STRING {
cold_path();
return invalid_initial_byte(byte);
}
Ok(alloc::borrow::Cow::Owned(self.read_binary_head(byte)?))
}
#[inline(always)]
fn read_option<T: FromCbor<'de>>(&mut self) -> Result<Option<T>> {
let byte = self.peek_initial_byte()?;
if byte == SIMPLE_VALUE_NULL {
self.read_byte()?;
Ok(None)
} else {
Ok(Some(T::read(self)?))
}
}
fn skip_value(&mut self) -> Result<()> {
self.increment_depth()?;
let byte = self.read_byte()?;
let major_type = byte & MAJOR_TYPE_MASK;
let info = byte & !MAJOR_TYPE_MASK;
match major_type {
MAJOR_TYPE_UNSIGNED_INT | MAJOR_TYPE_NEGATIVE_INT | MAJOR_TYPE_TAG => {
self.skip_additional_info(info)?;
}
MAJOR_TYPE_BYTE_STRING | MAJOR_TYPE_TEXT_STRING => {
if info == ADDITIONAL_INFO_INDEFINITE {
while self.read_chunk(major_type)?.is_some() {}
} else {
let len = usize::try_from(self.skip_additional_info(info)?)
.map_err(|_| Error::IntegerOutOfRange)?;
let _ = self.read_exact_vec(len)?;
}
}
MAJOR_TYPE_ARRAY => {
if info == ADDITIONAL_INFO_INDEFINITE {
while !self.at_break()? {
self.skip_value()?;
}
self.read_break()?;
} else {
let len = usize::try_from(self.skip_additional_info(info)?)
.map_err(|_| Error::IntegerOutOfRange)?;
for _ in 0..len {
self.skip_value()?;
}
}
}
MAJOR_TYPE_MAP => {
if info == ADDITIONAL_INFO_INDEFINITE {
while !self.at_break()? {
self.skip_value()?;
self.skip_value()?;
}
self.read_break()?;
} else {
let len = usize::try_from(self.skip_additional_info(info)?)
.map_err(|_| Error::IntegerOutOfRange)?;
for _ in 0..len {
self.skip_value()?;
self.skip_value()?;
}
}
}
MAJOR_TYPE_SIMPLE_FLOAT => match info {
0..=23 | 31 => {}
ADDITIONAL_INFO_1_BYTE => {
let mut buf = [0u8; 1];
self.read_exact(&mut buf)?;
}
ADDITIONAL_INFO_2_BYTES => {
let mut buf = [0u8; 2];
self.read_exact(&mut buf)?;
}
ADDITIONAL_INFO_4_BYTES => {
let mut buf = [0u8; 4];
self.read_exact(&mut buf)?;
}
ADDITIONAL_INFO_8_BYTES => {
let mut buf = [0u8; 8];
self.read_exact(&mut buf)?;
}
_ => {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
},
_ => {
cold_path();
return Err(Error::InvalidInitialByte(byte));
}
}
self.decrement_depth();
Ok(())
}
}
#[cfg(feature = "std")]
impl<R: std::io::Read> IOReader<R> {
#[inline(never)]
fn read_exact_into(&mut self, len: usize, out: &mut alloc::vec::Vec<u8>) -> Result<()> {
const CHUNK_SIZE: usize = 8192;
out.clear();
if len == 0 {
return Ok(());
} else if len < CHUNK_SIZE {
let mut buf = [0u8; CHUNK_SIZE];
self.reader
.read_exact(&mut buf[..len])
.map_err(Error::IoError)?;
out.extend_from_slice(&buf[..len]);
return Ok(());
}
let mut chunk = [0u8; CHUNK_SIZE];
let mut remaining = len;
while remaining > 0 {
let to_read = core::cmp::min(remaining, chunk.len());
let n = self
.reader
.read(&mut chunk[..to_read])
.map_err(Error::IoError)?;
if n == 0 {
cold_path();
return Err(Error::BufferTooSmall);
}
out.extend_from_slice(&chunk[..n]);
remaining -= n;
}
Ok(())
}
#[inline(always)]
fn skip_additional_info(&mut self, info: u8) -> Result<u64> {
match info {
0..=23 => Ok(info as u64),
ADDITIONAL_INFO_1_BYTE => {
let val = self.read_byte()? as u64;
Ok(val)
}
ADDITIONAL_INFO_2_BYTES => {
let mut bytes = [0; 2];
self.read_exact(&mut bytes)?;
Ok(u16::from_be_bytes(bytes) as u64)
}
ADDITIONAL_INFO_4_BYTES => {
let mut bytes = [0; 4];
self.read_exact(&mut bytes)?;
Ok(u32::from_be_bytes(bytes) as u64)
}
ADDITIONAL_INFO_8_BYTES => {
let mut bytes = [0; 8];
self.read_exact(&mut bytes)?;
Ok(u64::from_be_bytes(bytes))
}
ADDITIONAL_INFO_INDEFINITE => {
cold_path();
Err(Error::InvalidAdditionalInfo(ADDITIONAL_INFO_INDEFINITE))
}
_ => {
cold_path();
Err(Error::InvalidInitialByte(info))
}
}
}
}