use core::borrow::BorrowMut;
use crate::common::MAX_BLOCK_SIZE;
use crate::decoding::errors::FrameDecoderError;
use crate::decoding::{BlockDecodingStrategy, DictionaryHandle, FrameDecoder};
#[cfg(not(feature = "std"))]
use crate::io::ErrorKind;
use crate::io::{Error, Read};
pub struct StreamingDecoder<READ: Read, DEC: BorrowMut<FrameDecoder>> {
pub decoder: DEC,
source: READ,
dict: Option<DictionaryHandle>,
}
impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
pub fn new_with_decoder(
mut source: READ,
mut decoder: DEC,
) -> Result<StreamingDecoder<READ, DEC>, FrameDecoderError> {
decoder.borrow_mut().init(&mut source)?;
Ok(StreamingDecoder {
decoder,
source,
dict: None,
})
}
}
impl<READ: Read> StreamingDecoder<READ, FrameDecoder> {
pub fn new(
mut source: READ,
) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
let mut decoder = FrameDecoder::new();
decoder.init(&mut source)?;
Ok(StreamingDecoder {
decoder,
source,
dict: None,
})
}
pub fn new_with_dictionary_handle(
mut source: READ,
dict: &DictionaryHandle,
) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
let mut decoder = FrameDecoder::new();
decoder.init_with_dict_handle(&mut source, dict)?;
Ok(StreamingDecoder {
decoder,
source,
dict: Some(dict.clone()),
})
}
pub fn new_with_dictionary_bytes(
source: READ,
raw_dictionary: &[u8],
) -> Result<StreamingDecoder<READ, FrameDecoder>, FrameDecoderError> {
let dict = DictionaryHandle::decode_dict(raw_dictionary)?;
Self::new_with_dictionary_handle(source, &dict)
}
}
impl<READ: Read, DEC: BorrowMut<FrameDecoder>> StreamingDecoder<READ, DEC> {
pub fn get_ref(&self) -> &READ {
&self.source
}
pub fn get_mut(&mut self) -> &mut READ {
&mut self.source
}
pub fn into_inner(self) -> READ
where
READ: Sized,
{
self.source
}
pub fn into_parts(self) -> (READ, DEC)
where
READ: Sized,
{
(self.source, self.decoder)
}
pub fn into_frame_decoder(self) -> DEC {
self.decoder
}
}
impl<READ: Read, DEC: BorrowMut<FrameDecoder>> Read for StreamingDecoder<READ, DEC> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let decoder = self.decoder.borrow_mut();
if decoder.is_finished() && decoder.can_collect() == 0 {
#[cfg(feature = "hash")]
if let Err(e) = decoder.verify_content_checksum() {
#[cfg(feature = "std")]
return Err(Error::other(e));
#[cfg(not(feature = "std"))]
return Err(Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)));
}
return Ok(0);
}
let mut written = 0;
while written < buf.len() {
written += decoder.read(&mut buf[written..])?;
if written == buf.len() || decoder.is_finished() {
break;
}
let step = (buf.len() - written).min(MAX_BLOCK_SIZE as usize);
if let Err(e) =
decoder.decode_blocks(&mut self.source, BlockDecodingStrategy::UptoBytes(step))
{
#[cfg(feature = "std")]
{
return Err(Error::other(e));
}
#[cfg(not(feature = "std"))]
{
return Err(Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)));
}
}
}
#[cfg(feature = "hash")]
if written == 0
&& decoder.is_finished()
&& decoder.can_collect() == 0
&& let Err(e) = decoder.verify_content_checksum()
{
#[cfg(feature = "std")]
return Err(Error::other(e));
#[cfg(not(feature = "std"))]
return Err(Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)));
}
Ok(written)
}
#[cfg(feature = "std")]
fn read_to_end(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<usize, Error> {
let start_total = output.len();
let at_start = {
let d = self.decoder.borrow_mut();
d.is_at_frame_start() && d.can_collect() == 0
};
let dict = self.dict.clone();
if at_start {
let mut compressed = alloc::vec::Vec::new();
self.source.read_to_end(&mut compressed)?;
self.decoder
.borrow_mut()
.decode_current_frame_to_vec(&compressed, output, dict.as_ref())
.map_err(Error::other)?;
return Ok(output.len() - start_total);
}
loop {
let start = output.len();
output.resize(start + MAX_BLOCK_SIZE as usize, 0);
let n = match self.read(&mut output[start..]) {
Ok(n) => n,
Err(e) => {
output.truncate(start);
return Err(e);
}
};
output.truncate(start + n);
if n == 0 {
break;
}
}
let mut rest = alloc::vec::Vec::new();
self.source.read_to_end(&mut rest)?;
if !rest.is_empty() {
let mut input = rest.as_slice();
self.decoder
.borrow_mut()
.decode_concatenated_frames_to_vec(&mut input, output, dict.as_ref())
.map_err(Error::other)?;
}
Ok(output.len() - start_total)
}
#[cfg(not(feature = "std"))]
fn read_to_end(&mut self, output: &mut alloc::vec::Vec<u8>) -> Result<(), Error> {
let at_start = {
let d = self.decoder.borrow_mut();
d.is_at_frame_start() && d.can_collect() == 0
};
let dict = self.dict.clone();
if at_start {
let mut compressed = alloc::vec::Vec::new();
self.source.read_to_end(&mut compressed)?;
self.decoder
.borrow_mut()
.decode_current_frame_to_vec(&compressed, output, dict.as_ref())
.map_err(|e| Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)))?;
return Ok(());
}
loop {
let start = output.len();
output.resize(start + MAX_BLOCK_SIZE as usize, 0);
let n = match self.read(&mut output[start..]) {
Ok(n) => n,
Err(e) => {
output.truncate(start);
return Err(e);
}
};
output.truncate(start + n);
if n == 0 {
break;
}
}
let mut rest = alloc::vec::Vec::new();
self.source.read_to_end(&mut rest)?;
if !rest.is_empty() {
let mut input = rest.as_slice();
self.decoder
.borrow_mut()
.decode_concatenated_frames_to_vec(&mut input, output, dict.as_ref())
.map_err(|e| Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)))?;
}
Ok(())
}
}
#[cfg(test)]
mod tests;