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}