1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use crate::{codec::Decode, util::PartialBuffer}; use std::io::{Error, ErrorKind, Result}; use flate2::{Decompress, FlushDecompress, Status}; #[derive(Debug)] pub struct FlateDecoder { zlib_header: bool, decompress: Decompress, } impl FlateDecoder { pub(crate) fn new(zlib_header: bool) -> Self { Self { zlib_header, decompress: Decompress::new(zlib_header), } } fn decode( &mut self, input: &mut PartialBuffer<impl AsRef<[u8]>>, output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>, flush: FlushDecompress, ) -> Result<Status> { let prior_in = self.decompress.total_in(); let prior_out = self.decompress.total_out(); let status = self.decompress .decompress(input.unwritten(), output.unwritten_mut(), flush)?; input.advance((self.decompress.total_in() - prior_in) as usize); output.advance((self.decompress.total_out() - prior_out) as usize); Ok(status) } } impl Decode for FlateDecoder { fn reinit(&mut self) -> Result<()> { self.decompress.reset(self.zlib_header); Ok(()) } fn decode( &mut self, input: &mut PartialBuffer<impl AsRef<[u8]>>, output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>, ) -> Result<bool> { match self.decode(input, output, FlushDecompress::None)? { Status::Ok => Ok(false), Status::StreamEnd => Ok(true), Status::BufError => Err(Error::new(ErrorKind::Other, "unexpected BufError")), } } fn flush( &mut self, output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>, ) -> Result<bool> { self.decode( &mut PartialBuffer::new(&[][..]), output, FlushDecompress::Sync, )?; loop { let old_len = output.written().len(); self.decode( &mut PartialBuffer::new(&[][..]), output, FlushDecompress::None, )?; if output.written().len() == old_len { break; } } Ok(!output.unwritten().is_empty()) } fn finish( &mut self, output: &mut PartialBuffer<impl AsRef<[u8]> + AsMut<[u8]>>, ) -> Result<bool> { match self.decode( &mut PartialBuffer::new(&[][..]), output, FlushDecompress::Finish, )? { Status::Ok => Ok(false), Status::StreamEnd => Ok(true), Status::BufError => Err(Error::new(ErrorKind::Other, "unexpected BufError")), } } }