compression_codecs/flate/
decoder.rs

1use crate::DecodeV2;
2use compression_core::util::{PartialBuffer, WriteBuffer};
3use flate2::{Decompress, FlushDecompress, Status};
4use std::io;
5
6#[derive(Debug)]
7pub struct FlateDecoder {
8    zlib_header: bool,
9    decompress: Decompress,
10}
11
12impl FlateDecoder {
13    pub(crate) fn new(zlib_header: bool) -> Self {
14        Self {
15            zlib_header,
16            decompress: Decompress::new(zlib_header),
17        }
18    }
19
20    fn decode(
21        &mut self,
22        input: &mut PartialBuffer<&[u8]>,
23        output: &mut WriteBuffer<'_>,
24        flush: FlushDecompress,
25    ) -> io::Result<Status> {
26        let prior_in = self.decompress.total_in();
27        let prior_out = self.decompress.total_out();
28
29        let result = self
30            .decompress
31            // Safety: We **trust** flate2 to not write uninitialized bytes into buffer
32            .decompress_uninit(input.unwritten(), unsafe { output.unwritten_mut() }, flush);
33
34        input.advance((self.decompress.total_in() - prior_in) as usize);
35        // Safety: We **trust** flate2 to write bytes into buffer properly
36        unsafe {
37            output.assume_init_and_advance((self.decompress.total_out() - prior_out) as usize)
38        };
39
40        Ok(result?)
41    }
42}
43
44impl DecodeV2 for FlateDecoder {
45    fn reinit(&mut self) -> io::Result<()> {
46        self.decompress.reset(self.zlib_header);
47        Ok(())
48    }
49
50    fn decode(
51        &mut self,
52        input: &mut PartialBuffer<&[u8]>,
53        output: &mut WriteBuffer<'_>,
54    ) -> io::Result<bool> {
55        match self.decode(input, output, FlushDecompress::None)? {
56            Status::Ok => Ok(false),
57            Status::StreamEnd => Ok(true),
58            Status::BufError => Err(io::Error::other("unexpected BufError")),
59        }
60    }
61
62    fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
63        self.decode(
64            &mut PartialBuffer::new(&[][..]),
65            output,
66            FlushDecompress::Sync,
67        )?;
68
69        loop {
70            let old_len = output.written_len();
71            self.decode(
72                &mut PartialBuffer::new(&[][..]),
73                output,
74                FlushDecompress::None,
75            )?;
76            if output.written_len() == old_len {
77                break;
78            }
79        }
80
81        Ok(!output.has_no_spare_space())
82    }
83
84    fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
85        match self.decode(
86            &mut PartialBuffer::new(&[][..]),
87            output,
88            FlushDecompress::Finish,
89        )? {
90            Status::Ok => Ok(false),
91            Status::StreamEnd => Ok(true),
92            Status::BufError => Err(io::Error::other("unexpected BufError")),
93        }
94    }
95}