use crate::{decode::Decode, Error, Result};
use core::str;
#[cfg(feature = "base64")]
pub type Base64Reader<'i> = base64::Decoder<'i, base64::Base64>;
pub trait Reader: Sized {
fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]>;
fn remaining_len(&self) -> usize;
fn is_finished(&self) -> bool {
self.remaining_len() == 0
}
fn read_prefixed<'r, T, E, F>(&'r mut self, f: F) -> core::result::Result<T, E>
where
E: From<Error>,
F: FnOnce(&mut NestedReader<'r, Self>) -> core::result::Result<T, E>,
{
let len = usize::decode(self)?;
f(&mut NestedReader {
inner: self,
remaining_len: len,
})
}
fn read_byten<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
self.read_prefixed(|reader| {
let slice = out.get_mut(..reader.remaining_len()).ok_or(Error::Length)?;
reader.read(slice)?;
Ok(slice as &[u8])
})
}
fn read_string<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o str> {
Ok(str::from_utf8(self.read_byten(buf)?)?)
}
fn drain(&mut self, n_bytes: usize) -> Result<()> {
let mut byte = [0];
for _ in 0..n_bytes {
self.read(&mut byte)?;
}
Ok(())
}
fn drain_prefixed(&mut self) -> Result<usize> {
self.read_prefixed(|reader| {
let len = reader.remaining_len();
reader.drain(len)?;
Ok(len)
})
}
fn finish<T>(self, value: T) -> Result<T> {
if self.is_finished() {
Ok(value)
} else {
Err(Error::TrailingData {
remaining: self.remaining_len(),
})
}
}
}
impl Reader for &[u8] {
fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
if self.len() >= out.len() {
let (head, tail) = self.split_at(out.len());
*self = tail;
out.copy_from_slice(head);
Ok(out)
} else {
Err(Error::Length)
}
}
fn remaining_len(&self) -> usize {
self.len()
}
}
#[cfg(feature = "base64")]
impl Reader for Base64Reader<'_> {
fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
Ok(self.decode(out)?)
}
fn remaining_len(&self) -> usize {
self.remaining_len()
}
}
#[cfg(feature = "pem")]
impl Reader for pem::Decoder<'_> {
fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
Ok(self.decode(out)?)
}
fn remaining_len(&self) -> usize {
self.remaining_len()
}
}
pub struct NestedReader<'r, R: Reader> {
inner: &'r mut R,
remaining_len: usize,
}
impl<'r, R: Reader> Reader for NestedReader<'r, R> {
fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
let remaining_len = self
.remaining_len
.checked_sub(out.len())
.ok_or(Error::Length)?;
let ret = self.inner.read(out)?;
self.remaining_len = remaining_len;
Ok(ret)
}
fn remaining_len(&self) -> usize {
self.remaining_len
}
}