use std::io::{Read, Result as IoResult};
use crate::Error;
#[inline]
pub fn advance_read<R: Read + ?Sized>(reader: &mut R, mut len: usize) -> Result<(), Error> {
let mut buf = [0u8; 4096];
while len > 0 {
let chunk = len.min(buf.len());
reader.read_exact(&mut buf[..chunk]).map_err(Error::Io)?;
len -= chunk;
}
Ok(())
}
#[derive(Clone, Copy, Debug)]
pub struct SliceReader<'a> {
inner: &'a [u8],
original_len: usize,
}
impl<'a> SliceReader<'a> {
#[inline]
pub fn new(slice: &'a [u8]) -> Self {
Self {
original_len: slice.len(),
inner: slice,
}
}
#[inline]
pub fn remaining(&self) -> &[u8] {
self.inner
}
#[inline]
pub fn consumed_len(&self) -> usize {
self.original_len - self.inner.len()
}
#[inline]
pub fn consume(&mut self, n: usize) -> Result<(), Error> {
if n > self.inner.len() {
return Err(Error::Io(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected EOF while skipping",
)));
}
self.inner = &self.inner[n..];
Ok(())
}
}
impl Read for SliceReader<'_> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
let n = buf.len().min(self.inner.len());
buf[..n].copy_from_slice(&self.inner[..n]);
self.inner = &self.inner[n..];
Ok(n)
}
}
pub trait BorrowedReader: Read {
fn peek_bytes(&self, n: usize) -> Result<&[u8], Error>;
fn advance(&mut self, n: usize) -> Result<(), Error>;
}
impl BorrowedReader for &[u8] {
#[inline]
fn peek_bytes(&self, n: usize) -> Result<&[u8], Error> {
self.get(..n).ok_or_else(|| {
Error::Io(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected EOF while peeking borrowed bytes",
))
})
}
#[inline]
fn advance(&mut self, n: usize) -> Result<(), Error> {
if n > self.len() {
return Err(Error::Io(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected EOF while advancing slice reader",
)));
}
*self = &self[n..];
Ok(())
}
}
impl<'a> BorrowedReader for SliceReader<'a> {
#[inline]
fn peek_bytes(&self, n: usize) -> Result<&[u8], Error> {
self.inner.get(..n).ok_or_else(|| {
Error::Io(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected EOF while peeking borrowed bytes",
))
})
}
#[inline]
fn advance(&mut self, n: usize) -> Result<(), Error> {
self.consume(n)
}
}