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        let result = 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            Err(io::Error::other("brotli error"))
46        } else {
47            Ok(())
48        };
49
50        input.advance(input_len);
51        output.advance(output_len);
52
53        result
54    }
55}
56
57impl EncodeV2 for BrotliEncoder {
58    fn encode(
59        &mut self,
60        input: &mut PartialBuffer<&[u8]>,
61        output: &mut WriteBuffer<'_>,
62    ) -> io::Result<()> {
63        self.encode(
64            input,
65            output,
66            BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
67        )
68    }
69
70    fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
71        self.encode(
72            &mut PartialBuffer::new(&[][..]),
73            output,
74            BrotliEncoderOperation::BROTLI_OPERATION_FLUSH,
75        )?;
76
77        Ok(!self.state.has_more_output())
78    }
79
80    fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
81        self.encode(
82            &mut PartialBuffer::new(&[][..]),
83            output,
84            BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
85        )?;
86
87        Ok(self.state.is_finished())
88    }
89}
90
91impl fmt::Debug for BrotliEncoder {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        f.debug_struct("BrotliEncoder")
94            .field("compress", &"<no debug>")
95            .finish()
96    }
97}