use super::BorrowReader;
use crate::error::{Error, Result};
pub trait Reader {
fn read(&mut self, bytes: &mut [u8]) -> Result<()>;
}
pub struct SliceReader<'a> {
pub(crate) slice: &'a [u8],
}
impl<'a> SliceReader<'a> {
pub fn new(slice: &'a [u8]) -> Self {
Self { slice }
}
pub fn remaining(&self) -> &'a [u8] {
self.slice
}
}
impl<'a> Reader for SliceReader<'a> {
fn read(&mut self, bytes: &mut [u8]) -> Result<()> {
let len = bytes.len();
if self.slice.len() < len {
return Err(Error::UnexpectedEnd {
additional: len - self.slice.len(),
});
}
bytes.copy_from_slice(&self.slice[..len]);
self.slice = &self.slice[len..];
Ok(())
}
}
impl<'a> BorrowReader<'a> for SliceReader<'a> {
fn take_bytes(&mut self, length: usize) -> Result<&'a [u8]> {
if self.slice.len() < length {
return Err(Error::UnexpectedEnd {
additional: length - self.slice.len(),
});
}
let (bytes, rest) = self.slice.split_at(length);
self.slice = rest;
Ok(bytes)
}
fn peek_read(&self, n: usize) -> Option<&'a [u8]> {
if self.slice.len() >= n {
Some(&self.slice[..n])
} else {
None
}
}
fn consume(&mut self, n: usize) {
if self.slice.len() >= n {
self.slice = &self.slice[n..];
}
}
}
pub type SliceReaderBorrow<'a> = SliceReader<'a>;
#[cfg(feature = "std")]
pub struct IoReader<R: std::io::Read> {
reader: R,
}
#[cfg(feature = "std")]
impl<R: std::io::Read> IoReader<R> {
pub fn new(reader: R) -> Self {
Self { reader }
}
pub fn inner(&self) -> &R {
&self.reader
}
pub fn inner_mut(&mut self) -> &mut R {
&mut self.reader
}
pub fn into_inner(self) -> R {
self.reader
}
}
#[cfg(feature = "std")]
impl<R: std::io::Read> Reader for IoReader<R> {
fn read(&mut self, bytes: &mut [u8]) -> Result<()> {
self.reader.read_exact(bytes).map_err(|e| {
if e.kind() == std::io::ErrorKind::UnexpectedEof {
Error::UnexpectedEnd {
additional: bytes.len(),
}
} else {
Error::Io {
kind: e.kind(),
message: e.to_string(),
}
}
})
}
}
#[cfg(feature = "std")]
pub type StdReader<R> = IoReader<R>;
#[cfg(feature = "std")]
pub struct BufferedIoReader<R: std::io::Read> {
inner: std::io::BufReader<R>,
}
#[cfg(feature = "std")]
impl<R: std::io::Read> BufferedIoReader<R> {
pub fn new(reader: R) -> Self {
Self {
inner: std::io::BufReader::new(reader),
}
}
pub fn with_capacity(capacity: usize, reader: R) -> Self {
Self {
inner: std::io::BufReader::with_capacity(capacity, reader),
}
}
pub fn inner(&self) -> &R {
self.inner.get_ref()
}
pub fn inner_mut(&mut self) -> &mut R {
self.inner.get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner()
}
}
#[cfg(feature = "std")]
impl<R: std::io::Read> Reader for BufferedIoReader<R> {
fn read(&mut self, bytes: &mut [u8]) -> crate::error::Result<()> {
use std::io::Read as _;
self.inner
.read_exact(bytes)
.map_err(|e| crate::error::Error::Io {
kind: e.kind(),
message: e.to_string(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_slice_reader() {
let data = [0x42, 0x43, 0x44, 0x45];
let mut reader = SliceReader::new(&data);
let mut buf = [0u8; 1];
reader.read(&mut buf).expect("Failed to read");
assert_eq!(buf[0], 0x42);
assert_eq!(reader.remaining().len(), 3);
let mut buf = [0u8; 2];
reader.read(&mut buf).expect("Failed to read");
assert_eq!(buf, [0x43, 0x44]);
assert_eq!(reader.remaining().len(), 1);
let mut buf = [0u8; 2];
assert!(reader.read(&mut buf).is_err()); }
}