use std::io::Read;
use bytes::BytesMut;
use crate::{
v2::read::{
decoder::{DecodeError, Decoder},
Section,
},
DetectError, Version,
};
const DEFAULT_READ_SIZE: usize = 4 * 1024;
#[derive(Debug)]
pub struct StreamingReader<R> {
inner: R,
buffer: BytesMut,
}
impl<R: Read> StreamingReader<R> {
pub fn new(mut reader: R) -> Result<Self, StreamingReaderError> {
let version = crate::detect(&mut reader)?;
if version != Version::V2 {
return Err(StreamingReaderError::UnsupportedVersion(version));
}
Ok(StreamingReader {
inner: reader,
buffer: BytesMut::new(),
})
}
pub fn sections(mut self) -> impl Iterator<Item = Result<Section, StreamingReaderError>> {
std::iter::from_fn(move || self.next_section().transpose())
}
pub fn next_section(&mut self) -> Result<Option<Section>, StreamingReaderError> {
loop {
let bytes_read = self.fill_buffer()?;
match Decoder.decode(&mut self.buffer)? {
Some(section) => return Ok(Some(section)),
None if bytes_read != 0 => {
}
None => return Ok(None),
}
}
}
fn fill_buffer(&mut self) -> Result<usize, std::io::Error> {
let original_length = self.buffer.len();
self.buffer.resize(original_length + DEFAULT_READ_SIZE, 0);
let scratch_space = &mut self.buffer[original_length..];
let bytes_read = self.inner.read(scratch_space)?;
self.buffer.truncate(original_length + bytes_read);
Ok(bytes_read)
}
}
#[derive(Debug, thiserror::Error)]
pub enum StreamingReaderError {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("Unable to detect the WEBC version")]
Detect(#[from] DetectError),
#[error("The version, {_0}, isn't supported")]
UnsupportedVersion(Version),
#[error("Decode failed")]
Decode(#[from] DecodeError),
}