use std::io;
use crate::error::EndOrError;
use crate::parser::{Options, Parse, Parser, RawParser, WithOptions};
pub fn as_eof_flag(r: io::Result<()>) -> io::Result<bool> {
match r {
Err(e) if e.kind() == io::ErrorKind::WouldBlock => Ok(false),
Err(other) => Err(other),
Ok(()) => Ok(true),
}
}
#[derive(Debug)]
pub struct GenericReader<T: io::BufRead, P: Parse> {
parser: P,
reader: T,
}
impl<T: io::BufRead, P: Parse + Default> GenericReader<T, P> {
pub fn new(inner: T) -> Self {
Self::wrap(inner, P::default())
}
}
impl<T: io::BufRead, P: Parse + WithOptions> GenericReader<T, P> {
pub fn with_options(inner: T, options: Options) -> Self {
Self::wrap(inner, P::with_options(options))
}
}
impl<T: io::BufRead, P: Parse> GenericReader<T, P> {
pub fn wrap(inner: T, parser: P) -> Self {
Self {
reader: inner,
parser,
}
}
pub fn into_inner(self) -> (T, P) {
(self.reader, self.parser)
}
pub fn inner(&self) -> &T {
&self.reader
}
pub fn inner_mut(&mut self) -> &mut T {
&mut self.reader
}
pub fn parser(&self) -> &P {
&self.parser
}
pub fn parser_mut(&mut self) -> &mut P {
&mut self.parser
}
pub fn read(&mut self) -> io::Result<Option<P::Output>> {
let mut empty: &[u8] = &[][..];
match self.parser.parse(&mut empty, false) {
Ok(v) => return Ok(v),
Err(EndOrError::NeedMoreData) => (),
Err(EndOrError::Error(other)) => {
return Err(io::Error::new(io::ErrorKind::InvalidData, other));
}
};
loop {
let mut buf = self.reader.fill_buf()?;
let init_len = buf.len();
let result = self.parser.parse(&mut buf, init_len == 0);
let new_len = buf.len();
let consumed = init_len - new_len;
self.reader.consume(consumed);
match result {
Ok(v) => return Ok(v),
Err(EndOrError::NeedMoreData) => {
assert!(consumed == init_len);
}
Err(EndOrError::Error(other)) => {
return Err(io::Error::new(io::ErrorKind::InvalidData, other));
}
}
}
}
pub fn read_all<F>(&mut self, mut callback: F) -> io::Result<()>
where
F: FnMut(P::Output),
{
loop {
match self.read()? {
None => return Ok(()),
Some(ev) => callback(ev),
}
}
}
#[inline(always)]
pub fn read_all_eof<F>(&mut self, callback: F) -> io::Result<bool>
where
F: FnMut(P::Output),
{
crate::as_eof_flag(self.read_all(callback))
}
pub fn release_temporaries(&mut self) {
self.parser.release_temporaries();
}
}
impl<T: io::BufRead, P: Parse> Iterator for GenericReader<T, P> {
type Item = io::Result<P::Output>;
fn next(&mut self) -> Option<Self::Item> {
self.read().transpose()
}
}
pub type Reader<T> = GenericReader<T, Parser>;
pub type RawReader<T> = GenericReader<T, RawParser>;