use core::fmt;
use core::marker;
use core::mem::MaybeUninit;
use core::ops::Range;
use core::ptr;
use core::slice;
use crate::Context;
use crate::de::UnsizedVisitor;
mod sealed {
use super::{Limit, Reader};
pub trait Sealed {}
impl Sealed for &[u8] {}
impl Sealed for super::SliceReader<'_> {}
impl<'de, R> Sealed for Limit<R> where R: Reader<'de> {}
impl<'de, R> Sealed for &mut R where R: ?Sized + Reader<'de> {}
}
pub trait IntoReader<'de>: self::sealed::Sealed {
type Reader: Reader<'de>;
fn into_reader(self) -> Self::Reader;
}
pub trait Reader<'de>: self::sealed::Sealed {
type Mut<'this>: Reader<'de>
where
Self: 'this;
type TryClone: Reader<'de>;
fn borrow_mut(&mut self) -> Self::Mut<'_>;
fn try_clone(&self) -> Option<Self::TryClone>;
fn is_eof(&mut self) -> bool;
fn skip<C>(&mut self, cx: C, n: usize) -> Result<(), C::Error>
where
C: Context;
fn peek(&mut self) -> Option<u8>;
#[inline]
fn read<C>(&mut self, cx: C, buf: &mut [u8]) -> Result<(), C::Error>
where
C: Context,
{
struct Visitor<'a>(&'a mut [u8]);
#[crate::trait_defaults(crate)]
impl<C> UnsizedVisitor<'_, C, [u8]> for Visitor<'_>
where
C: Context,
{
type Ok = ();
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "bytes")
}
#[inline]
fn visit_ref(self, _: C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
self.0.copy_from_slice(bytes);
Ok(())
}
}
self.read_bytes(cx, buf.len(), Visitor(buf))
}
fn read_bytes<C, V>(&mut self, cx: C, n: usize, visitor: V) -> Result<V::Ok, V::Error>
where
C: Context,
V: UnsizedVisitor<'de, C, [u8], Error = C::Error, Allocator = C::Allocator>;
unsafe fn read_bytes_uninit<C>(
&mut self,
cx: C,
ptr: *mut u8,
len: usize,
) -> Result<(), C::Error>
where
C: Context;
#[inline]
fn read_byte<C>(&mut self, cx: C) -> Result<u8, C::Error>
where
C: Context,
{
let [byte] = self.read_array::<C, 1>(cx)?;
Ok(byte)
}
#[inline]
fn read_array<C, const N: usize>(&mut self, cx: C) -> Result<[u8; N], C::Error>
where
C: Context,
{
struct Visitor<const N: usize>([u8; N]);
#[crate::trait_defaults(crate)]
impl<const N: usize, C> UnsizedVisitor<'_, C, [u8]> for Visitor<N>
where
C: Context,
{
type Ok = [u8; N];
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "bytes")
}
#[inline]
fn visit_ref(mut self, cx: C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
self.0.copy_from_slice(bytes);
cx.advance(bytes.len());
Ok(self.0)
}
}
self.read_bytes(cx, N, Visitor([0u8; N]))
}
#[inline]
fn limit(self, limit: usize) -> Limit<Self>
where
Self: Sized,
{
Limit {
remaining: limit,
reader: self,
}
}
}
impl<'de> IntoReader<'de> for &'de [u8] {
type Reader = &'de [u8];
#[inline]
fn into_reader(self) -> Self::Reader {
self
}
}
impl<'de> Reader<'de> for &'de [u8] {
type Mut<'this>
= &'this mut &'de [u8]
where
Self: 'this;
type TryClone = &'de [u8];
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn try_clone(&self) -> Option<Self::TryClone> {
Some(self)
}
#[inline]
fn is_eof(&mut self) -> bool {
self.is_empty()
}
#[inline]
fn skip<C>(&mut self, cx: C, n: usize) -> Result<(), C::Error>
where
C: Context,
{
if self.len() < n {
return Err(cx.message(SliceUnderflow {
n,
remaining: self.len(),
}));
}
let (_, tail) = self.split_at(n);
*self = tail;
cx.advance(n);
Ok(())
}
#[inline]
fn read<C>(&mut self, cx: C, buf: &mut [u8]) -> Result<(), C::Error>
where
C: Context,
{
if self.len() < buf.len() {
return Err(cx.custom(SliceUnderflow::new(buf.len(), self.len())));
}
let (head, tail) = self.split_at(buf.len());
buf.copy_from_slice(head);
*self = tail;
cx.advance(buf.len());
Ok(())
}
#[inline]
fn read_bytes<C, V>(&mut self, cx: C, n: usize, visitor: V) -> Result<V::Ok, V::Error>
where
C: Context,
V: UnsizedVisitor<'de, C, [u8], Error = C::Error, Allocator = C::Allocator>,
{
if self.len() < n {
return Err(cx.custom(SliceUnderflow::new(n, self.len())));
}
let (head, tail) = self.split_at(n);
*self = tail;
let ok = visitor.visit_borrowed(cx, head)?;
cx.advance(n);
Ok(ok)
}
#[inline]
unsafe fn read_bytes_uninit<C>(&mut self, cx: C, ptr: *mut u8, n: usize) -> Result<(), C::Error>
where
C: Context,
{
if self.len() < n {
return Err(cx.custom(SliceUnderflow::new(n, self.len())));
}
unsafe {
ptr.copy_from_nonoverlapping(self.as_ptr(), n);
}
*self = &self[n..];
cx.advance(n);
Ok(())
}
#[inline]
fn read_byte<C>(&mut self, cx: C) -> Result<u8, C::Error>
where
C: Context,
{
let &[first, ref tail @ ..] = *self else {
return Err(cx.custom(SliceUnderflow::new(1, self.len())));
};
*self = tail;
cx.advance(1);
Ok(first)
}
#[inline]
fn read_array<C, const N: usize>(&mut self, cx: C) -> Result<[u8; N], C::Error>
where
C: Context,
{
if self.len() < N {
return Err(cx.custom(SliceUnderflow::new(N, self.len())));
}
cx.advance(N);
let mut array: MaybeUninit<[u8; N]> = MaybeUninit::uninit();
unsafe {
array
.as_mut_ptr()
.cast::<u8>()
.copy_from_nonoverlapping(self.as_ptr(), N);
*self = self.get_unchecked(N..);
Ok(array.assume_init())
}
}
#[inline]
fn peek(&mut self) -> Option<u8> {
self.first().copied()
}
}
pub struct SliceReader<'de> {
range: Range<*const u8>,
_marker: marker::PhantomData<&'de [u8]>,
}
unsafe impl Send for SliceReader<'_> {}
unsafe impl Sync for SliceReader<'_> {}
impl<'de> SliceReader<'de> {
#[inline]
pub fn new(slice: &'de [u8]) -> Self {
Self {
range: slice.as_ptr_range(),
_marker: marker::PhantomData,
}
}
#[inline]
pub fn as_slice(&self) -> &'de [u8] {
unsafe { slice::from_raw_parts(self.range.start, self.remaining()) }
}
pub fn remaining(&self) -> usize {
self.range.end as usize - self.range.start as usize
}
}
impl<'de> Reader<'de> for SliceReader<'de> {
type Mut<'this>
= &'this mut Self
where
Self: 'this;
type TryClone = Self;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn try_clone(&self) -> Option<Self::TryClone> {
Some(Self {
range: self.range.clone(),
_marker: marker::PhantomData,
})
}
#[inline]
fn is_eof(&mut self) -> bool {
self.range.start == self.range.end
}
#[inline]
fn skip<C>(&mut self, cx: C, n: usize) -> Result<(), C::Error>
where
C: Context,
{
self.range.start = bounds_check_add(cx, &self.range, n)?;
cx.advance(n);
Ok(())
}
#[inline]
fn read_bytes<C, V>(&mut self, cx: C, n: usize, visitor: V) -> Result<V::Ok, V::Error>
where
C: Context,
V: UnsizedVisitor<'de, C, [u8], Error = C::Error, Allocator = C::Allocator>,
{
let outcome = bounds_check_add(cx, &self.range, n)?;
let ok = unsafe {
let bytes = slice::from_raw_parts(self.range.start, n);
self.range.start = outcome;
visitor.visit_borrowed(cx, bytes)?
};
cx.advance(n);
Ok(ok)
}
#[inline]
unsafe fn read_bytes_uninit<C>(&mut self, cx: C, ptr: *mut u8, n: usize) -> Result<(), C::Error>
where
C: Context,
{
let outcome = bounds_check_add(cx, &self.range, n)?;
unsafe {
ptr.copy_from_nonoverlapping(self.range.start, n);
}
self.range.start = outcome;
cx.advance(n);
Ok(())
}
#[inline]
fn peek(&mut self) -> Option<u8> {
if self.range.start == self.range.end {
return None;
}
unsafe { Some(ptr::read(self.range.start)) }
}
#[inline]
fn read<C>(&mut self, cx: C, buf: &mut [u8]) -> Result<(), C::Error>
where
C: Context,
{
let outcome = bounds_check_add(cx, &self.range, buf.len())?;
unsafe {
self.range
.start
.copy_to_nonoverlapping(buf.as_mut_ptr(), buf.len());
self.range.start = outcome;
}
cx.advance(buf.len());
Ok(())
}
}
#[inline]
fn bounds_check_add<C>(cx: C, range: &Range<*const u8>, len: usize) -> Result<*const u8, C::Error>
where
C: Context,
{
let outcome = range.start.wrapping_add(len);
if outcome > range.end || outcome < range.start {
Err(cx.message(SliceUnderflow {
n: len,
remaining: (range.end as usize).wrapping_sub(range.start as usize),
}))
} else {
Ok(outcome)
}
}
pub struct Limit<R> {
remaining: usize,
reader: R,
}
impl<R> Limit<R> {
#[inline]
pub fn remaining(&self) -> usize {
self.remaining
}
}
impl<'de, R> Limit<R>
where
R: Reader<'de>,
{
#[inline]
fn bounds_check<C>(&mut self, cx: C, n: usize) -> Result<(), C::Error>
where
C: Context,
{
match self.remaining.checked_sub(n) {
Some(remaining) => {
self.remaining = remaining;
Ok(())
}
None => Err(cx.message("Reader out of bounds")),
}
}
}
impl<'de, R> Reader<'de> for Limit<R>
where
R: Reader<'de>,
{
type Mut<'this>
= &'this mut Self
where
Self: 'this;
type TryClone = Limit<R::TryClone>;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn try_clone(&self) -> Option<Self::TryClone> {
Some(Limit {
remaining: self.remaining,
reader: self.reader.try_clone()?,
})
}
#[inline]
fn is_eof(&mut self) -> bool {
self.remaining == 0 || self.reader.is_eof()
}
#[inline]
fn skip<C>(&mut self, cx: C, n: usize) -> Result<(), C::Error>
where
C: Context,
{
self.bounds_check(cx, n)?;
self.reader.skip(cx, n)
}
#[inline]
fn read_bytes<C, V>(&mut self, cx: C, n: usize, visitor: V) -> Result<V::Ok, V::Error>
where
C: Context,
V: UnsizedVisitor<'de, C, [u8], Error = C::Error, Allocator = C::Allocator>,
{
self.bounds_check(cx, n)?;
self.reader.read_bytes(cx, n, visitor)
}
#[inline]
unsafe fn read_bytes_uninit<C>(&mut self, cx: C, ptr: *mut u8, n: usize) -> Result<(), C::Error>
where
C: Context,
{
self.bounds_check(cx, n)?;
unsafe { self.reader.read_bytes_uninit(cx, ptr, n) }
}
#[inline]
fn peek(&mut self) -> Option<u8> {
if self.remaining > 0 {
self.reader.peek()
} else {
None
}
}
#[inline]
fn read<C>(&mut self, cx: C, buf: &mut [u8]) -> Result<(), C::Error>
where
C: Context,
{
self.bounds_check(cx, buf.len())?;
self.reader.read(cx, buf)
}
#[inline]
fn read_byte<C>(&mut self, cx: C) -> Result<u8, C::Error>
where
C: Context,
{
self.bounds_check(cx, 1)?;
self.reader.read_byte(cx)
}
#[inline]
fn read_array<C, const N: usize>(&mut self, cx: C) -> Result<[u8; N], C::Error>
where
C: Context,
{
self.bounds_check(cx, N)?;
self.reader.read_array(cx)
}
}
impl<'a, 'de, R> IntoReader<'de> for &'a mut R
where
R: ?Sized + Reader<'de>,
{
type Reader = &'a mut R;
#[inline]
fn into_reader(self) -> Self::Reader {
self
}
}
impl<'de, R> Reader<'de> for &mut R
where
R: ?Sized + Reader<'de>,
{
type Mut<'this>
= &'this mut R
where
Self: 'this;
type TryClone = R::TryClone;
#[inline]
fn borrow_mut(&mut self) -> Self::Mut<'_> {
self
}
#[inline]
fn try_clone(&self) -> Option<Self::TryClone> {
(**self).try_clone()
}
#[inline]
fn is_eof(&mut self) -> bool {
(**self).is_eof()
}
#[inline]
fn skip<C>(&mut self, cx: C, n: usize) -> Result<(), C::Error>
where
C: Context,
{
(**self).skip(cx, n)
}
#[inline]
fn read_bytes<C, V>(&mut self, cx: C, n: usize, visitor: V) -> Result<V::Ok, V::Error>
where
C: Context,
V: UnsizedVisitor<'de, C, [u8], Error = C::Error, Allocator = C::Allocator>,
{
(**self).read_bytes(cx, n, visitor)
}
#[inline]
unsafe fn read_bytes_uninit<C>(&mut self, cx: C, ptr: *mut u8, n: usize) -> Result<(), C::Error>
where
C: Context,
{
unsafe { (**self).read_bytes_uninit(cx, ptr, n) }
}
#[inline]
fn peek(&mut self) -> Option<u8> {
(**self).peek()
}
#[inline]
fn read<C>(&mut self, cx: C, buf: &mut [u8]) -> Result<(), C::Error>
where
C: Context,
{
(**self).read(cx, buf)
}
#[inline]
fn read_byte<C>(&mut self, cx: C) -> Result<u8, C::Error>
where
C: Context,
{
(**self).read_byte(cx)
}
#[inline]
fn read_array<C, const N: usize>(&mut self, cx: C) -> Result<[u8; N], C::Error>
where
C: Context,
{
(**self).read_array(cx)
}
}
#[derive(Debug)]
pub(crate) struct SliceUnderflow {
n: usize,
remaining: usize,
}
impl SliceUnderflow {
#[inline]
pub(crate) fn new(n: usize, remaining: usize) -> Self {
Self { n, remaining }
}
}
impl fmt::Display for SliceUnderflow {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let SliceUnderflow { n, remaining } = self;
write!(
f,
"Tried to read {n} bytes from slice, with {remaining} byte remaining"
)
}
}
impl core::error::Error for SliceUnderflow {}