compression_codecs/mzstd/
encoder.rs1use crate::{
2 mzstd::params::{encoder_config, CParameter},
3 EncodeV2,
4};
5use compression_core::util::{PartialBuffer, WriteBuffer};
6use mzstd::{
7 dictionary::DictionaryBuilder, Compressor, EncoderSessionOwned, EncoderStatus, Operation,
8 StreamConfig,
9};
10use std::io;
11
12fn process(
16 session: &mut EncoderSessionOwned,
17 input: &[u8],
18 output: &mut WriteBuffer<'_>,
19 operation: Operation,
20) -> io::Result<(usize, EncoderStatus)> {
21 let progress = session
23 .process_uninit(input, unsafe { output.unwritten_mut() }, operation)
24 .map_err(io::Error::other)?;
25 unsafe { output.assume_init_and_advance(progress.produced) };
27 Ok((progress.consumed, progress.status))
28}
29
30#[derive(Debug)]
31pub struct MzstdEncoder {
32 session: EncoderSessionOwned,
33}
34
35impl MzstdEncoder {
36 pub fn new(level: i32) -> Self {
37 Self::new_with_params(level, &[])
38 }
39
40 pub fn new_with_params(level: i32, params: &[CParameter]) -> Self {
44 let compressor = Compressor::new(encoder_config(level, params)).unwrap();
45 Self {
46 session: compressor.into_session(StreamConfig::default()),
47 }
48 }
49
50 pub fn new_with_dict(level: i32, dictionary: &[u8]) -> io::Result<Self> {
51 let config = encoder_config(level, &[]);
52 let dictionary = DictionaryBuilder::new(dictionary)
53 .with_config(config)
54 .build()
55 .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
56 let session = Compressor::new(config)
58 .unwrap()
59 .into_session_with_dictionary(dictionary, StreamConfig::default())
60 .map_err(io::Error::other)?;
61 Ok(Self { session })
62 }
63}
64
65impl EncodeV2 for MzstdEncoder {
66 fn encode(
67 &mut self,
68 input: &mut PartialBuffer<&[u8]>,
69 output: &mut WriteBuffer<'_>,
70 ) -> io::Result<()> {
71 let (consumed, _) = process(
72 &mut self.session,
73 input.unwritten(),
74 output,
75 Operation::Continue,
76 )?;
77 input.advance(consumed);
78
79 Ok(())
80 }
81
82 fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
83 let (_, status) = process(&mut self.session, &[], output, Operation::Flush)?;
84
85 match status {
86 EncoderStatus::NeedsInput | EncoderStatus::Finished => Ok(true),
87 EncoderStatus::NeedsOutput => Ok(false),
88 }
89 }
90
91 fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
92 let (_, status) = process(&mut self.session, &[], output, Operation::End)?;
93
94 match status {
95 EncoderStatus::Finished => Ok(true),
96 EncoderStatus::NeedsInput | EncoderStatus::NeedsOutput => Ok(false),
97 }
98 }
99}