Skip to main content

compression_codecs/brotli/
encoder.rs

1use crate::{brotli::params::EncoderParams, EncodeV2};
2use brotli::enc::{
3    backward_references::BrotliEncoderParams,
4    encode::{BrotliEncoderOperation, BrotliEncoderStateStruct},
5    StandardAlloc,
6};
7use compression_core::util::{PartialBuffer, WriteBuffer};
8use std::{fmt, io};
9
10pub struct BrotliEncoder {
11    state: BrotliEncoderStateStruct<StandardAlloc>,
12}
13
14impl BrotliEncoder {
15    pub fn new(params: EncoderParams) -> Self {
16        let params = BrotliEncoderParams::from(params);
17        let mut state = BrotliEncoderStateStruct::new(StandardAlloc::default());
18        state.params = params;
19        Self { state }
20    }
21
22    fn encode(
23        &mut self,
24        input: &mut PartialBuffer<&[u8]>,
25        output: &mut WriteBuffer<'_>,
26        op: BrotliEncoderOperation,
27    ) -> io::Result<()> {
28        let in_buf = input.unwritten();
29        let out_buf = output.initialize_unwritten();
30
31        let mut input_len = 0;
32        let mut output_len = 0;
33
34        if !self.state.compress_stream(
35            op,
36            &mut in_buf.len(),
37            in_buf,
38            &mut input_len,
39            &mut out_buf.len(),
40            out_buf,
41            &mut output_len,
42            &mut None,
43            &mut |_, _, _, _| (),
44        ) {
45            return Err(io::Error::other("brotli error"));
46        }
47
48        input.advance(input_len);
49        output.advance(output_len);
50
51        Ok(())
52    }
53}
54
55impl EncodeV2 for BrotliEncoder {
56    fn encode(
57        &mut self,
58        input: &mut PartialBuffer<&[u8]>,
59        output: &mut WriteBuffer<'_>,
60    ) -> io::Result<()> {
61        self.encode(
62            input,
63            output,
64            BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
65        )
66    }
67
68    fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
69        self.encode(
70            &mut PartialBuffer::new(&[][..]),
71            output,
72            BrotliEncoderOperation::BROTLI_OPERATION_FLUSH,
73        )?;
74
75        Ok(!self.state.has_more_output())
76    }
77
78    fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
79        self.encode(
80            &mut PartialBuffer::new(&[][..]),
81            output,
82            BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
83        )?;
84
85        Ok(self.state.is_finished())
86    }
87}
88
89impl fmt::Debug for BrotliEncoder {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        f.debug_struct("BrotliEncoder")
92            .field("compress", &"<no debug>")
93            .finish()
94    }
95}