use {
core::mem,
std::io::{Bytes, Error, ErrorKind, Read},
crate::{
Result,
read_only_u64::ReadOnlyU64,
},
};
#[derive(Debug)]
pub struct Stream<R> where R: Read {
src: Bytes<R>,
max_size: ReadOnlyU64,
limit: usize,
}
impl<R> Stream<R> where R: Read {
pub fn make(src: R, max_size: u64) -> Result<Self> {
let limit = if mem::size_of::<usize>() >= mem::size_of::<u64>() || usize::max_value() as u64 >= max_size {
max_size as usize
} else {
return Err(Error::new(ErrorKind::InvalidInput, format!(
"max_size is too large: {max_size}, max allowed: {max_size_allowed}", max_size=max_size, max_size_allowed=usize::max_value(),
)));
};
Ok(Self {
src: src.bytes(),
max_size: max_size.into(),
limit,
})
}
}
impl<R> Iterator for Stream<R> where R: Read {
type Item = Result<String>;
fn next(&mut self) -> Option<Self::Item> {
let mut buf = Vec::with_capacity(self.limit.min(1024));
fn parse_buf<F>(buf: Vec<u8>, limit: &mut usize, if_empty: F) -> Option<Result<String>> where F: FnOnce() -> Option<Result<String>> {
match buf.len() {
0 => if_empty(),
buf_len => {
*limit = limit.saturating_sub(buf_len);
match String::from_utf8(buf) {
Ok(s) => Some(Ok(s)),
Err(err) => Some(Err(Error::new(ErrorKind::Other, err))),
}
},
}
}
loop {
match self.src.next() {
Some(Ok(0)) => return parse_buf(buf, &mut self.limit, || Some(Ok(String::new()))),
Some(Ok(b)) => if buf.len() < self.limit {
buf.push(b);
} else {
self.limit = 0;
return Some(Err(Error::new(
ErrorKind::InvalidData, format!("Input data is too large, max allowed: {} bytes", *self.max_size),
)));
},
Some(Err(err)) => {
self.limit = self.limit.saturating_sub(buf.len());
return Some(Err(err));
},
None => return parse_buf(buf, &mut self.limit, || None),
};
}
}
}