use core::fmt;
use super::{DecodeErr, Decoder};
use crate::util::{Buffer, ByteSource, ByteSourceErr};
#[derive(Debug, PartialEq)]
pub enum ReadDecodedError<IoErr> {
DecodeErr(DecodeErr),
IoErr(IoErr, usize),
}
impl fmt::Display for ReadDecodedError<fmt::Error> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Debug>::fmt(self, f)
}
}
#[cfg(feature = "std")]
impl std::error::Error for ReadDecodedError<fmt::Error> {}
pub struct DecoderReader<B, R>
where
B: Buffer,
R: ByteSource,
{
decoder: Decoder<B>,
reader: R,
}
impl<B, R> DecoderReader<B, R>
where
B: Buffer,
R: ByteSource,
{
pub fn new(reader: R) -> Self {
DecoderReader {
decoder: Default::default(),
reader,
}
}
pub fn read(&mut self) -> Result<&[u8], ReadDecodedError<R::ReadError>> {
loop {
match self.reader.read_byte() {
Ok(b) => match self.decoder._push_byte(b) {
Ok(false) => continue,
Ok(true) => return Ok(self.decoder.borrow_buf()),
Err(e) => return Err(ReadDecodedError::DecodeErr(e)),
},
Err(e) => {
assert!(!(e.is_eof() && e.is_would_block()));
let discarded_bytes = if !e.is_would_block() {
self.decoder.reset()
} else {
0
};
return Err(ReadDecodedError::IoErr(e, discarded_bytes));
}
}
}
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<Result<&[u8], ReadDecodedError<R::ReadError>>> {
match self.read() {
Err(ReadDecodedError::IoErr(e, 0)) if e.is_eof() => None,
x => Some(x),
}
}
#[cfg(feature = "nb")]
pub fn read_nb(&mut self) -> nb::Result<&[u8], ReadDecodedError<R::ReadError>> {
self.read().map_err(|e| match e {
ReadDecodedError::IoErr(io_err, _) if io_err.is_would_block() => nb::Error::WouldBlock,
other => nb::Error::Other(other),
})
}
#[cfg(feature = "nb")]
pub fn next_nb(&mut self) -> nb::Result<Option<&[u8]>, ReadDecodedError<R::ReadError>> {
match self.read_nb() {
Err(nb::Error::Other(ReadDecodedError::IoErr(e, 0))) if e.is_eof() => Ok(None),
Err(e) => Err(e),
Ok(x) => Ok(Some(x)),
}
}
}
#[cfg(test)]
mod decoder_reader_tests {
use core::iter::once;
use crate::util::ArrayBuf;
use super::*;
use hex_literal::hex;
struct TestReader<I>
where
I: Iterator<Item = Result<u8, TestReaderErr>>,
{
iter: I,
}
impl<I> ByteSource for TestReader<I>
where
I: Iterator<Item = Result<u8, TestReaderErr>>,
{
type ReadError = TestReaderErr;
fn read_byte(&mut self) -> Result<u8, Self::ReadError> {
self.iter.next().unwrap_or(Err(TestReaderErr::Eof))
}
}
impl<I> crate::util::private::Sealed for TestReader<I> where
I: Iterator<Item = Result<u8, TestReaderErr>>
{
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum TestReaderErr {
Eof,
Other,
WouldBlock,
}
impl ByteSourceErr for TestReaderErr {
fn is_eof(&self) -> bool {
matches!(self, TestReaderErr::Eof)
}
fn is_would_block(&self) -> bool {
matches!(self, TestReaderErr::WouldBlock)
}
}
impl crate::util::private::Sealed for TestReaderErr {}
fn decoder_from<I>(iter: I) -> DecoderReader<ArrayBuf<1024>, TestReader<I>>
where
I: Iterator<Item = Result<u8, TestReaderErr>>,
{
DecoderReader {
decoder: Default::default(),
reader: TestReader { iter },
}
}
#[test]
fn successful_read_then_eof() {
let data = hex!("1b1b1b1b 01010101 12345678 1b1b1b1b 1a00b87b");
let mut dr = decoder_from(data.into_iter().map(Ok));
assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
assert_eq!(dr.next(), None);
}
#[test]
fn eof_while_parsing() {
let data = hex!("1b1b1b1b 01010101 12");
let mut dr = decoder_from(data.into_iter().map(Ok));
assert_eq!(
dr.next(),
Some(Err(ReadDecodedError::IoErr(TestReaderErr::Eof, 9)))
);
assert_eq!(dr.next(), None);
assert_eq!(dr.next(), None);
}
#[test]
fn err_while_parsing_ok_afterwards() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("1b1b1b1b 01010101 12345678 1b1b1b1b 1a00b87b")
.into_iter()
.map(Ok);
let all_data = data.chain(once(Err(TestReaderErr::Other))).chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(
dr.next(),
Some(Err(ReadDecodedError::IoErr(TestReaderErr::Other, 9)))
);
assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
assert_eq!(dr.next(), None);
assert_eq!(dr.next(), None);
}
#[test]
fn would_block_while_parsing() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
let all_data = data
.chain(once(Err(TestReaderErr::WouldBlock)))
.chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(
dr.next(),
Some(Err(ReadDecodedError::IoErr(TestReaderErr::WouldBlock, 0)))
);
assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
assert_eq!(dr.next(), None);
assert_eq!(dr.next(), None);
}
#[test]
fn would_block_before_parsing() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
let all_data = once(Err(TestReaderErr::WouldBlock))
.chain(data)
.chain(once(Err(TestReaderErr::WouldBlock)))
.chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(
dr.next(),
Some(Err(ReadDecodedError::IoErr(TestReaderErr::WouldBlock, 0)))
);
assert_eq!(
dr.next(),
Some(Err(ReadDecodedError::IoErr(TestReaderErr::WouldBlock, 0)))
);
assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
assert_eq!(dr.next(), None);
assert_eq!(dr.next(), None);
}
#[test]
fn immediate_err() {
let all_data = once(Err(TestReaderErr::Other));
let mut dr = decoder_from(all_data);
assert_eq!(
dr.next(),
Some(Err(ReadDecodedError::IoErr(TestReaderErr::Other, 0)))
);
assert_eq!(dr.next(), None);
assert_eq!(dr.next(), None);
}
#[test]
#[cfg(feature = "nb")]
fn read_nb() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
let all_data = once(Err(TestReaderErr::WouldBlock))
.chain(data)
.chain(once(Err(TestReaderErr::WouldBlock)))
.chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(dr.read_nb(), Err(nb::Error::WouldBlock));
assert_eq!(dr.read_nb(), Err(nb::Error::WouldBlock));
assert_eq!(dr.read_nb(), Ok(hex!("12345678").as_slice()));
assert_eq!(
dr.read_nb(),
Err(nb::Error::Other(ReadDecodedError::IoErr(
TestReaderErr::Eof,
0
)))
);
assert_eq!(
dr.read_nb(),
Err(nb::Error::Other(ReadDecodedError::IoErr(
TestReaderErr::Eof,
0
)))
);
}
#[test]
#[cfg(feature = "nb")]
fn next_nb() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
let all_data = once(Err(TestReaderErr::WouldBlock))
.chain(data)
.chain(once(Err(TestReaderErr::WouldBlock)))
.chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(dr.next_nb(), Err(nb::Error::WouldBlock));
assert_eq!(dr.next_nb(), Err(nb::Error::WouldBlock));
assert_eq!(dr.next_nb(), Ok(Some(hex!("12345678").as_slice())));
assert_eq!(dr.next_nb(), Ok(None));
assert_eq!(dr.next_nb(), Ok(None));
}
#[test]
#[cfg(feature = "nb")]
fn nb_block_next_nb() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
let all_data = once(Err(TestReaderErr::WouldBlock))
.chain(data)
.chain(once(Err(TestReaderErr::WouldBlock)))
.chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(
nb::block!(dr.next_nb()),
Ok(Some(hex!("12345678").as_slice()))
);
assert_eq!(nb::block!(dr.next_nb()), Ok(None));
assert_eq!(nb::block!(dr.next_nb()), Ok(None));
}
#[test]
#[cfg(feature = "nb")]
fn nb_block_read_nb() {
let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
let all_data = once(Err(TestReaderErr::WouldBlock))
.chain(data)
.chain(once(Err(TestReaderErr::WouldBlock)))
.chain(data2);
let mut dr = decoder_from(all_data);
assert_eq!(nb::block!(dr.read_nb()), Ok(hex!("12345678").as_slice()));
assert_eq!(
nb::block!(dr.read_nb()),
Err(ReadDecodedError::IoErr(TestReaderErr::Eof, 0))
);
assert_eq!(
nb::block!(dr.read_nb()),
Err(ReadDecodedError::IoErr(TestReaderErr::Eof, 0))
);
}
}