compression_codecs/zstd/
encoder.rs

1use crate::zstd::params::CParameter;
2use crate::Encode;
3use compression_core::unshared::Unshared;
4use compression_core::util::PartialBuffer;
5use libzstd::stream::raw::{Encoder, Operation};
6use std::io;
7use std::io::Result;
8
9#[derive(Debug)]
10pub struct ZstdEncoder {
11    encoder: Unshared<Encoder<'static>>,
12}
13
14impl ZstdEncoder {
15    pub fn new(level: i32) -> Self {
16        Self {
17            encoder: Unshared::new(Encoder::new(level).unwrap()),
18        }
19    }
20
21    pub fn new_with_params(level: i32, params: &[CParameter]) -> Self {
22        let mut encoder = Encoder::new(level).unwrap();
23        for param in params {
24            encoder.set_parameter(param.as_zstd()).unwrap();
25        }
26        Self {
27            encoder: Unshared::new(encoder),
28        }
29    }
30
31    pub fn new_with_dict(level: i32, dictionary: &[u8]) -> io::Result<Self> {
32        let encoder = Encoder::with_dictionary(level, dictionary)?;
33        Ok(Self {
34            encoder: Unshared::new(encoder),
35        })
36    }
37}
38
39impl Encode for ZstdEncoder {
40    fn encode(
41        &mut self,
42        input: &mut PartialBuffer<impl AsRef<[u8]>>,
43        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
44    ) -> Result<()> {
45        let status = self
46            .encoder
47            .get_mut()
48            .run_on_buffers(input.unwritten(), output.unwritten_mut())?;
49        input.advance(status.bytes_read);
50        output.advance(status.bytes_written);
51        Ok(())
52    }
53
54    fn flush(
55        &mut self,
56        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
57    ) -> Result<bool> {
58        let mut out_buf = zstd_safe::OutBuffer::around(output.unwritten_mut());
59        let bytes_left = self.encoder.get_mut().flush(&mut out_buf)?;
60        let len = out_buf.as_slice().len();
61        output.advance(len);
62        Ok(bytes_left == 0)
63    }
64
65    fn finish(
66        &mut self,
67        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
68    ) -> Result<bool> {
69        let mut out_buf = zstd_safe::OutBuffer::around(output.unwritten_mut());
70        let bytes_left = self.encoder.get_mut().finish(&mut out_buf, true)?;
71        let len = out_buf.as_slice().len();
72        output.advance(len);
73        Ok(bytes_left == 0)
74    }
75}