use crate::{
mzstd::params::{decoder_config, DParameter},
DecodeV2,
};
use compression_core::util::{PartialBuffer, WriteBuffer};
use mzstd::{
dictionary::{DecodeDictionary, DictionaryContent},
DecodeOperation, DecoderSessionOwned, DecoderStatus, Decompressor,
};
use std::io;
#[derive(Debug)]
pub struct MzstdDecoder {
session: DecoderSessionOwned,
}
impl Default for MzstdDecoder {
fn default() -> Self {
Self::new_with_params(&[])
}
}
impl MzstdDecoder {
pub fn new() -> Self {
Self::default()
}
pub fn new_with_params(params: &[DParameter]) -> Self {
let session = Decompressor::new(decoder_config(params)).into_session();
Self { session }
}
pub fn new_with_dict(dictionary: &[u8]) -> io::Result<Self> {
let dictionary = DecodeDictionary::new(dictionary, DictionaryContent::Auto)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
let session =
Decompressor::new(decoder_config(&[])).into_session_with_dictionary(dictionary);
Ok(Self { session })
}
}
fn process(
session: &mut DecoderSessionOwned,
input: &[u8],
output: &mut WriteBuffer<'_>,
operation: DecodeOperation,
) -> (usize, io::Result<DecoderStatus>) {
let result = session.process_uninit(input, unsafe { output.unwritten_mut() }, operation);
match result {
Ok(progress) => {
unsafe { output.assume_init_and_advance(progress.produced) };
(progress.consumed, Ok(progress.status))
}
Err(failure) => {
unsafe { output.assume_init_and_advance(failure.produced) };
(failure.consumed, Err(failure.into_error().into()))
}
}
}
impl DecodeV2 for MzstdDecoder {
fn reinit(&mut self) -> io::Result<()> {
self.session.reinit();
Ok(())
}
fn decode(
&mut self,
input: &mut PartialBuffer<&[u8]>,
output: &mut WriteBuffer<'_>,
) -> io::Result<bool> {
let (consumed, status) = process(
&mut self.session,
input.unwritten(),
output,
DecodeOperation::Process,
);
input.advance(consumed);
match status? {
DecoderStatus::Finished => Ok(true),
DecoderStatus::NeedsInput | DecoderStatus::NeedsOutput => Ok(false),
}
}
fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
let (_, status) = process(&mut self.session, &[], output, DecodeOperation::Process);
match status? {
DecoderStatus::Finished | DecoderStatus::NeedsInput => Ok(true),
DecoderStatus::NeedsOutput => Ok(false),
}
}
fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
let (_, status) = process(&mut self.session, &[], output, DecodeOperation::Finish);
match status? {
DecoderStatus::Finished => Ok(true),
DecoderStatus::NeedsInput | DecoderStatus::NeedsOutput => Ok(false),
}
}
}