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 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}