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