compression_codecs/bzip2/
decoder.rs

1use crate::Decode;
2use bzip2::{Decompress, Status};
3use compression_core::util::PartialBuffer;
4use std::{fmt, io};
5
6pub struct BzDecoder {
7    decompress: Decompress,
8}
9
10impl fmt::Debug for BzDecoder {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        write!(
13            f,
14            "BzDecoder {{total_in: {}, total_out: {}}}",
15            self.decompress.total_in(),
16            self.decompress.total_out()
17        )
18    }
19}
20
21impl Default for BzDecoder {
22    fn default() -> Self {
23        Self {
24            decompress: Decompress::new(false),
25        }
26    }
27}
28
29impl BzDecoder {
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    fn decode(
35        &mut self,
36        input: &mut PartialBuffer<impl AsRef<[u8]>>,
37        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
38    ) -> io::Result<Status> {
39        let prior_in = self.decompress.total_in();
40        let prior_out = self.decompress.total_out();
41
42        let status = self
43            .decompress
44            .decompress(input.unwritten(), output.unwritten_mut())
45            .map_err(io::Error::other)?;
46
47        input.advance((self.decompress.total_in() - prior_in) as usize);
48        output.advance((self.decompress.total_out() - prior_out) as usize);
49
50        Ok(status)
51    }
52}
53
54impl Decode for BzDecoder {
55    fn reinit(&mut self) -> io::Result<()> {
56        self.decompress = Decompress::new(false);
57        Ok(())
58    }
59
60    fn decode(
61        &mut self,
62        input: &mut PartialBuffer<impl AsRef<[u8]>>,
63        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
64    ) -> io::Result<bool> {
65        match self.decode(input, output)? {
66            // Decompression went fine, nothing much to report.
67            Status::Ok => Ok(false),
68
69            // The Flush action on a compression went ok.
70            Status::FlushOk => unreachable!(),
71
72            // THe Run action on compression went ok.
73            Status::RunOk => unreachable!(),
74
75            // The Finish action on compression went ok.
76            Status::FinishOk => unreachable!(),
77
78            // The stream's end has been met, meaning that no more data can be input.
79            Status::StreamEnd => Ok(true),
80
81            // There was insufficient memory in the input or output buffer to complete
82            // the request, but otherwise everything went normally.
83            Status::MemNeeded => Err(io::Error::other("out of memory")),
84        }
85    }
86
87    fn flush(
88        &mut self,
89        output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
90    ) -> io::Result<bool> {
91        self.decode(&mut PartialBuffer::new(&[][..]), output)?;
92
93        loop {
94            let old_len = output.written().len();
95            self.decode(&mut PartialBuffer::new(&[][..]), output)?;
96            if output.written().len() == old_len {
97                break;
98            }
99        }
100
101        Ok(!output.unwritten().is_empty())
102    }
103
104    fn finish(
105        &mut self,
106        _output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>,
107    ) -> io::Result<bool> {
108        Ok(true)
109    }
110}