async_compression_issue_150_workaround/codec/brotli/
decoder.rs1use crate::{codec::Decode, util::PartialBuffer};
2use std::{
3 fmt,
4 io::{Error, ErrorKind, Result},
5};
6
7use brotli::{enc::StandardAlloc, BrotliDecompressStream, BrotliResult, BrotliState};
8
9pub struct BrotliDecoder {
10 state: BrotliState<StandardAlloc, StandardAlloc, StandardAlloc>,
11}
12
13impl BrotliDecoder {
14 pub fn new() -> Self {
15 Self {
16 state: BrotliState::new(
17 StandardAlloc::default(),
18 StandardAlloc::default(),
19 StandardAlloc::default(),
20 ),
21 }
22 }
23
24 fn decode(
25 &mut self,
26 input: &mut PartialBuffer<impl AsRef<[u8]>>,
27 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
28 ) -> Result<BrotliResult> {
29 let in_buf = input.unwritten();
30 let mut out_buf = output.unwritten_mut();
31
32 let mut input_len = 0;
33 let mut output_len = 0;
34
35 let status = match BrotliDecompressStream(
36 &mut in_buf.len(),
37 &mut input_len,
38 in_buf,
39 &mut out_buf.len(),
40 &mut output_len,
41 out_buf,
42 &mut 0,
43 &mut self.state,
44 ) {
45 BrotliResult::ResultFailure => {
46 return Err(Error::new(ErrorKind::Other, "brotli error"))
47 }
48 status => status,
49 };
50
51 input.advance(input_len);
52 output.advance(output_len);
53
54 Ok(status)
55 }
56}
57
58impl Decode for BrotliDecoder {
59 fn reinit(&mut self) -> Result<()> {
60 self.state = BrotliState::new(
61 StandardAlloc::default(),
62 StandardAlloc::default(),
63 StandardAlloc::default(),
64 );
65 Ok(())
66 }
67
68 fn decode(
69 &mut self,
70 input: &mut PartialBuffer<impl AsRef<[u8]>>,
71 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
72 ) -> Result<bool> {
73 match self.decode(input, output)? {
74 BrotliResult::ResultSuccess => Ok(true),
75 BrotliResult::NeedsMoreOutput | BrotliResult::NeedsMoreInput => Ok(false),
76 BrotliResult::ResultFailure => unreachable!(),
77 }
78 }
79
80 fn flush(
81 &mut self,
82 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
83 ) -> Result<bool> {
84 match self.decode(&mut PartialBuffer::new(&[][..]), output)? {
85 BrotliResult::ResultSuccess | BrotliResult::NeedsMoreInput => Ok(true),
86 BrotliResult::NeedsMoreOutput => Ok(false),
87 BrotliResult::ResultFailure => unreachable!(),
88 }
89 }
90
91 fn finish(
92 &mut self,
93 output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
94 ) -> Result<bool> {
95 match self.decode(&mut PartialBuffer::new(&[][..]), output)? {
96 BrotliResult::ResultSuccess => Ok(true),
97 BrotliResult::NeedsMoreOutput => Ok(false),
98 BrotliResult::NeedsMoreInput => Err(Error::new(
99 ErrorKind::UnexpectedEof,
100 "reached unexpected EOF",
101 )),
102 BrotliResult::ResultFailure => unreachable!(),
103 }
104 }
105}
106
107impl fmt::Debug for BrotliDecoder {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.debug_struct("BrotliDecoder")
110 .field("decompress", &"<no debug>")
111 .finish()
112 }
113}