#![allow(unsafe_code)]
use crate::error::DecodeError;
pub trait Reader {
fn read(
&mut self,
bytes: &mut [u8],
) -> Result<(), DecodeError>;
#[inline(always)]
fn read_u8(&mut self) -> Result<u8, DecodeError> {
let mut byte = [0u8; 1];
self.read(&mut byte)?;
Ok(byte[0])
}
#[inline(always)]
fn read_u16(&mut self) -> Result<u16, DecodeError> {
let mut bytes = [0u8; 2];
self.read(&mut bytes)?;
Ok(u16::from_ne_bytes(bytes))
}
#[inline(always)]
fn read_u32(&mut self) -> Result<u32, DecodeError> {
let mut bytes = [0u8; 4];
self.read(&mut bytes)?;
Ok(u32::from_ne_bytes(bytes))
}
#[inline(always)]
fn read_u64(&mut self) -> Result<u64, DecodeError> {
let mut bytes = [0u8; 8];
self.read(&mut bytes)?;
Ok(u64::from_ne_bytes(bytes))
}
#[inline(always)]
fn read_u128(&mut self) -> Result<u128, DecodeError> {
let mut bytes = [0u8; 16];
self.read(&mut bytes)?;
Ok(u128::from_ne_bytes(bytes))
}
#[inline(always)]
fn peek_read(
&mut self,
_: usize,
) -> Option<&[u8]> {
None
}
#[inline(always)]
fn consume(
&mut self,
_: usize,
) {
}
#[inline(always)]
fn peek_u8(&mut self) -> Option<u8> {
self.peek_read(1).map(|b| b[0])
}
}
impl<T> Reader for &mut T
where
T: Reader,
{
#[inline(always)]
fn read(
&mut self,
bytes: &mut [u8],
) -> Result<(), DecodeError> {
(**self).read(bytes)
}
#[inline(always)]
fn peek_read(
&mut self,
n: usize,
) -> Option<&[u8]> {
(**self).peek_read(n)
}
#[inline(always)]
fn consume(
&mut self,
n: usize,
) {
(*self).consume(n);
}
#[inline(always)]
fn read_u16(&mut self) -> Result<u16, DecodeError> {
(**self).read_u16()
}
#[inline(always)]
fn read_u32(&mut self) -> Result<u32, DecodeError> {
(**self).read_u32()
}
#[inline(always)]
fn read_u64(&mut self) -> Result<u64, DecodeError> {
(**self).read_u64()
}
#[inline(always)]
fn read_u128(&mut self) -> Result<u128, DecodeError> {
(**self).read_u128()
}
}
pub trait BorrowReader<'storage>: Reader {
fn take_bytes(
&mut self,
length: usize,
) -> Result<&'storage [u8], DecodeError>;
}
pub struct SliceReader<'storage> {
pub(crate) slice: &'storage [u8],
}
impl<'storage> SliceReader<'storage> {
#[must_use]
pub const fn new(bytes: &'storage [u8]) -> Self {
Self { slice: bytes }
}
}
impl<'storage> Reader for SliceReader<'storage> {
#[inline(always)]
fn read(
&mut self,
bytes: &mut [u8],
) -> Result<(), DecodeError> {
if bytes.len() > self.slice.len() {
return crate::error::cold_decode_error_unexpected_end(bytes.len() - self.slice.len());
}
unsafe {
core::ptr::copy_nonoverlapping(self.slice.as_ptr(), bytes.as_mut_ptr(), bytes.len());
self.slice = self.slice.get_unchecked(bytes.len()..);
}
Ok(())
}
#[inline(always)]
fn peek_read(
&mut self,
n: usize,
) -> Option<&'storage [u8]> {
self.slice.get(..n)
}
#[inline(always)]
fn consume(
&mut self,
n: usize,
) {
if n >= self.slice.len() {
self.slice = &[];
} else {
self.slice = unsafe { self.slice.get_unchecked(n..) };
}
}
#[inline(always)]
fn peek_u8(&mut self) -> Option<u8> {
self.slice.first().copied()
}
#[inline(always)]
fn read_u8(&mut self) -> Result<u8, DecodeError> {
if self.slice.is_empty() {
return crate::error::cold_decode_error_unexpected_end(1);
}
let byte = unsafe { *self.slice.get_unchecked(0) };
self.slice = unsafe { self.slice.get_unchecked(1..) };
Ok(byte)
}
#[inline(always)]
fn read_u16(&mut self) -> Result<u16, DecodeError> {
if self.slice.len() < 2 {
return crate::error::cold_decode_error_unexpected_end(2 - self.slice.len());
}
let val = unsafe { core::ptr::read_unaligned(self.slice.as_ptr().cast::<u16>()) };
self.slice = unsafe { self.slice.get_unchecked(2..) };
Ok(val)
}
#[inline(always)]
fn read_u32(&mut self) -> Result<u32, DecodeError> {
if self.slice.len() < 4 {
return crate::error::cold_decode_error_unexpected_end(4 - self.slice.len());
}
let val = unsafe { core::ptr::read_unaligned(self.slice.as_ptr().cast::<u32>()) };
self.slice = unsafe { self.slice.get_unchecked(4..) };
Ok(val)
}
#[inline(always)]
fn read_u64(&mut self) -> Result<u64, DecodeError> {
if self.slice.len() < 8 {
return crate::error::cold_decode_error_unexpected_end(8 - self.slice.len());
}
let val = unsafe { core::ptr::read_unaligned(self.slice.as_ptr().cast::<u64>()) };
self.slice = unsafe { self.slice.get_unchecked(8..) };
Ok(val)
}
#[inline(always)]
fn read_u128(&mut self) -> Result<u128, DecodeError> {
if self.slice.len() < 16 {
return crate::error::cold_decode_error_unexpected_end(16 - self.slice.len());
}
let val = unsafe { core::ptr::read_unaligned(self.slice.as_ptr().cast::<u128>()) };
self.slice = unsafe { self.slice.get_unchecked(16..) };
Ok(val)
}
}
impl<'storage> BorrowReader<'storage> for SliceReader<'storage> {
#[inline(always)]
fn take_bytes(
&mut self,
length: usize,
) -> Result<&'storage [u8], DecodeError> {
if length > self.slice.len() {
return crate::error::cold_decode_error_unexpected_end(length - self.slice.len());
}
unsafe {
let read_slice = self.slice.get_unchecked(..length);
self.slice = self.slice.get_unchecked(length..);
Ok(read_slice)
}
}
}