use core::{marker::PhantomData, fmt::Debug};
pub trait Read<'read>: Sized + Debug {
type Error: Sized + Copy + Debug;
fn read_byte(&mut self) -> Result<u8, Self::Error>;
fn read_exact(&mut self, slice: &mut [u8]) -> Result<(), Self::Error>;
}
pub(crate) struct PeekableRead<'read, R: Read<'read>> {
buffer: u8,
reader: R,
_read: PhantomData<&'read ()>,
}
impl<'read, R: Read<'read>> PeekableRead<'read, R> {
pub(crate) fn try_from(mut reader: R) -> Result<Self, R::Error> {
Ok(Self { buffer: reader.read_byte()?, reader, _read: PhantomData })
}
}
impl<'read, R: Read<'read>> PeekableRead<'read, R> {
#[must_use]
#[inline(always)]
pub(crate) fn peek(&self) -> u8 {
self.buffer
}
#[inline(always)]
pub(crate) fn read_byte(&mut self) -> Result<u8, R::Error> {
let res = self.buffer;
self.buffer = self.reader.read_byte()?;
Ok(res)
}
#[inline(always)]
pub(crate) fn read_exact_into_non_empty_slice(
&mut self,
slice: &mut [u8],
) -> Result<(), R::Error> {
slice[0] = self.buffer;
self.reader.read_exact(&mut slice[1 ..])?;
self.buffer = self.reader.read_byte()?;
Ok(())
}
}
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
pub enum SliceError {
Short(usize),
}
impl<'read> Read<'read> for &'read [u8] {
type Error = SliceError;
#[inline(always)]
fn read_byte(&mut self) -> Result<u8, Self::Error> {
let res = *self.first().ok_or(SliceError::Short(1))?;
*self = &self[1 ..];
Ok(res)
}
#[inline(always)]
fn read_exact(&mut self, slice: &mut [u8]) -> Result<(), Self::Error> {
if self.len() < slice.len() {
Err(SliceError::Short(slice.len() - self.len()))?;
}
slice.copy_from_slice(&self[.. slice.len()]);
*self = &self[slice.len() ..];
Ok(())
}
}
impl<'read, R: Read<'read>> Read<'read> for &mut R {
type Error = R::Error;
#[inline(always)]
fn read_byte(&mut self) -> Result<u8, Self::Error> {
R::read_byte(self)
}
#[inline(always)]
fn read_exact(&mut self, slice: &mut [u8]) -> Result<(), Self::Error> {
R::read_exact(self, slice)
}
}