compression_codecs/brotli/
encoder.rs1use 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}