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 =
30            self.decompress
31                .decompress(input.unwritten(), output.initialize_unwritten(), flush);
32
33        input.advance((self.decompress.total_in() - prior_in) as usize);
34        output.advance((self.decompress.total_out() - prior_out) as usize);
35
36        Ok(result?)
37    }
38}
39
40impl DecodeV2 for FlateDecoder {
41    fn reinit(&mut self) -> io::Result<()> {
42        self.decompress.reset(self.zlib_header);
43        Ok(())
44    }
45
46    fn decode(
47        &mut self,
48        input: &mut PartialBuffer<&[u8]>,
49        output: &mut WriteBuffer<'_>,
50    ) -> io::Result<bool> {
51        match self.decode(input, output, FlushDecompress::None)? {
52            Status::Ok => Ok(false),
53            Status::StreamEnd => Ok(true),
54            Status::BufError => Err(io::Error::other("unexpected BufError")),
55        }
56    }
57
58    fn flush(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
59        self.decode(
60            &mut PartialBuffer::new(&[][..]),
61            output,
62            FlushDecompress::Sync,
63        )?;
64
65        loop {
66            let old_len = output.written_len();
67            self.decode(
68                &mut PartialBuffer::new(&[][..]),
69                output,
70                FlushDecompress::None,
71            )?;
72            if output.written_len() == old_len {
73                break;
74            }
75        }
76
77        Ok(!output.has_no_spare_space())
78    }
79
80    fn finish(&mut self, output: &mut WriteBuffer<'_>) -> io::Result<bool> {
81        match self.decode(
82            &mut PartialBuffer::new(&[][..]),
83            output,
84            FlushDecompress::Finish,
85        )? {
86            Status::Ok => Ok(false),
87            Status::StreamEnd => Ok(true),
88            Status::BufError => Err(io::Error::other("unexpected BufError")),
89        }
90    }
91}