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