X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fcompr%2Fdeflate.rs;h=3a3819ef2eb4bea191ed55e7fe985f0c44b1b793;hb=9f838842665ed75d8fda65146a8a1268b62160ee;hp=e917519a520def5b570f14e3677b6bbba1d0beb7;hpb=11f1d51e5a08ce44ddcdc308fd2f6d942760e7d4;p=nihav.git diff --git a/nihav-core/src/compr/deflate.rs b/nihav-core/src/compr/deflate.rs index e917519..3a3819e 100644 --- a/nihav-core/src/compr/deflate.rs +++ b/nihav-core/src/compr/deflate.rs @@ -375,8 +375,15 @@ impl Inflate { ///! ///! [`DecompressError::ShortData`]: ../enum.DecompressError.html#variant.ShortData ///! [`DecompressError::OutputFull`]: ../enum.DecompressError.html#variant.OutputFull - #[allow(clippy::comparison_chain)] pub fn decompress_data(&mut self, src: &[u8], dst: &mut [u8], continue_block: bool) -> DecompressResult { + self.decompress_data_internal(src, dst, continue_block, false) + } + ///! Tries to decompress whole input chunk to the output buffer. + pub fn decompress_block(&mut self, src: &[u8], dst: &mut [u8]) -> DecompressResult { + self.decompress_data_internal(src, dst, false, true) + } + #[allow(clippy::comparison_chain)] + fn decompress_data_internal(&mut self, src: &[u8], dst: &mut [u8], continue_block: bool, do_one_block: bool) -> DecompressResult { if src.is_empty() || dst.is_empty() { return Err(DecompressError::InvalidArgument); } @@ -386,10 +393,25 @@ impl Inflate { self.output_idx = 0; CurrentSource::reinit(src, self.br) }; + if do_one_block { + self.output_idx = 0; + } + // check for zlib stream header + if let (&InflateState::Start, true) = (&self.state, src.len() > 2) { + let cm = src[0] & 0xF; + let cinfo = src[0] >> 4; + let hdr = (u16::from(src[0]) << 8) | u16::from(src[1]); + if cm == 8 && cinfo <= 7 && (hdr % 31) == 0 { + csrc.skip(16).unwrap(); + } + } 'main: loop { match self.state { InflateState::Start | InflateState::BlockStart => { if csrc.left() == 0 { + if do_one_block { + return Ok(self.output_idx); + } self.br = csrc.br; return Err(DecompressError::ShortData); } @@ -417,7 +439,7 @@ impl Inflate { }, InflateState::StaticBlockInvLen(len) => { let inv_len = read_bits!(self, csrc, 16); - if len != !inv_len { + if (len ^ inv_len) != 0xFFFF { self.state = InflateState::End; return Err(DecompressError::InvalidHeader); } @@ -734,11 +756,18 @@ impl Inflate { } } } + ///! Resets decoder state. + pub fn reset(&mut self) { + self.bpos = 0; + self.output_idx = 0; + self.full_pos = 0; + self.state = InflateState::Start; + } + ///! Decompresses input data into output returning the uncompressed data length. pub fn uncompress(src: &[u8], dst: &mut [u8]) -> DecompressResult { let mut inflate = Self::new(); - let off = if src.len() > 2 && src[0] == 0x78 && (src[1] != 0 && ((src[1] - 1) % 31) == 0) { 2 } else { 0 }; - inflate.decompress_data(&src[off..], dst, false) + inflate.decompress_data(src, dst, false) } } @@ -1710,17 +1739,17 @@ pub struct Deflate { sum1: u32, sum2: u32, zlib_mode: bool, - parser: Box, + parser: Box, } impl Deflate { ///! Creates a new instance of `Deflate`. pub fn new(mode: DeflateMode) -> Self { let (mode, parser) = match mode { - DeflateMode::NoCompr => (Mode::Copy, Box::new(NoParser{}) as Box), - DeflateMode::Fast => (Mode::Fixed, Box::new(GreedyParser{}) as Box), - DeflateMode::Better => (Mode::Dynamic, Box::new(LazyParser{}) as Box), - DeflateMode::Best => (Mode::Dynamic, Box::new(OptimalParser::new()) as Box), + DeflateMode::NoCompr => (Mode::Copy, Box::new(NoParser{}) as Box), + DeflateMode::Fast => (Mode::Fixed, Box::new(GreedyParser{}) as Box), + DeflateMode::Better => (Mode::Dynamic, Box::new(LazyParser{}) as Box), + DeflateMode::Best => (Mode::Dynamic, Box::new(OptimalParser::new()) as Box), }; Self { mode, parser,