async_compression/codec/flate/
decoder.rs

1use crate::{codec::Decode, util::PartialBuffer};
2use std::io;
3
4use flate2::{Decompress, FlushDecompress, Status};
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<impl AsRef<[u8]>>,
23        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
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 status =
30            self.decompress
31                .decompress(input.unwritten(), output.unwritten_mut(), 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(status)
37    }
38}
39
40impl Decode 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<impl AsRef<[u8]>>,
49        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
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::new(io::ErrorKind::Other, "unexpected BufError")),
55        }
56    }
57
58    fn flush(
59        &mut self,
60        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
61    ) -> io::Result<bool> {
62        self.decode(
63            &mut PartialBuffer::new(&[][..]),
64            output,
65            FlushDecompress::Sync,
66        )?;
67
68        loop {
69            let old_len = output.written().len();
70            self.decode(
71                &mut PartialBuffer::new(&[][..]),
72                output,
73                FlushDecompress::None,
74            )?;
75            if output.written().len() == old_len {
76                break;
77            }
78        }
79
80        Ok(!output.unwritten().is_empty())
81    }
82
83    fn finish(
84        &mut self,
85        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
86    ) -> io::Result<bool> {
87        match self.decode(
88            &mut PartialBuffer::new(&[][..]),
89            output,
90            FlushDecompress::Finish,
91        )? {
92            Status::Ok => Ok(false),
93            Status::StreamEnd => Ok(true),
94            Status::BufError => Err(io::Error::new(io::ErrorKind::Other, "unexpected BufError")),
95        }
96    }
97}