compression_codecs/flate/
decoder.rs1use 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 .decompress_uninit(input.unwritten(), unsafe { output.unwritten_mut() }, flush);
33
34 input.advance((self.decompress.total_in() - prior_in) as usize);
35 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}