compression_codecs/mbrotli/
decoder.rs1use crate::DecodeV2;
2use compression_core::util::{PartialBuffer, WriteBuffer};
3use mbrotli::{
4 DecodeOperation, DecodeStreamConfig, DecoderConfig, DecoderSessionOwned, DecoderStatus,
5 Decompressor, WindowLimit,
6};
7use std::io;
8
9const DECODER_CONFIG: DecoderConfig = DecoderConfig::new().with_window_limit(
12 match WindowLimit::standard(mbrotli::Window::MAX_STANDARD_BITS) {
13 Ok(limit) => limit,
14 Err(_) => panic!("the standard window limit is valid"),
15 },
16);
17
18#[derive(Debug)]
19pub struct MbrotliDecoder {
20 session: DecoderSessionOwned,
21}
22
23impl Default for MbrotliDecoder {
24 fn default() -> Self {
25 let decompressor = Decompressor::new(DECODER_CONFIG).unwrap();
26 let session = decompressor
28 .into_session(DecodeStreamConfig::default())
29 .unwrap();
30 Self { session }
31 }
32}
33
34impl MbrotliDecoder {
35 pub fn new() -> Self {
36 Self::default()
37 }
38}
39
40fn process(
44 session: &mut DecoderSessionOwned,
45 input: &[u8],
46 output: &mut WriteBuffer<'_>,
47 operation: DecodeOperation,
48) -> (usize, io::Result<DecoderStatus>) {
49 let result = session.process_uninit(input, unsafe { output.unwritten_mut() }, operation);
51 match result {
54 Ok(progress) => {
55 unsafe { output.assume_init_and_advance(progress.produced) };
57 (progress.consumed, Ok(progress.status))
58 }
59 Err(failure) => {
60 unsafe { output.assume_init_and_advance(failure.produced) };
62 (failure.consumed, Err(failure.into_error().into()))
63 }
64 }
65}
66
67impl DecodeV2 for MbrotliDecoder {
68 fn reinit(&mut self) -> io::Result<()> {
69 self.session.reinit(DecodeStreamConfig::default())?;
70 Ok(())
71 }
72
73 fn decode(
74 &mut self,
75 input: &mut PartialBuffer<&[u8]>,
76 output: &mut WriteBuffer<'_>,
77 ) -> io::Result<bool> {
78 let (consumed, status) = process(
79 &mut self.session,
80 input.unwritten(),
81 output,
82 DecodeOperation::Process,
83 );
84 input.advance(consumed);
85
86 match status? {
87 DecoderStatus::Finished => Ok(true),
88 DecoderStatus::NeedsInput | DecoderStatus::NeedsOutput => Ok(false),
89 }
90 }
91
92 fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
93 let (_, status) = process(&mut self.session, &[], output, DecodeOperation::Process);
95
96 match status? {
97 DecoderStatus::Finished | DecoderStatus::NeedsInput => Ok(true),
98 DecoderStatus::NeedsOutput => Ok(false),
99 }
100 }
101
102 fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
103 let (_, status) = process(&mut self.session, &[], output, DecodeOperation::Finish);
105
106 match status? {
107 DecoderStatus::Finished => Ok(true),
108 DecoderStatus::NeedsInput | DecoderStatus::NeedsOutput => Ok(false),
109 }
110 }
111}