1 //! Deflate format (RFC 1951) support.
3 //! This module provides functionality for decompressing raw deflated streams via [`Inflate`] and gzip files (RFC 1952) via [`gzip_decode`].
5 //! [`Inflate`]: ./struct.Inflate.html
6 //! [`gzip_decode`]: ./fn.gzip_decode.html
10 //! Decompressing full input buffer into sufficiently large output buffer:
12 //! # use nihav_core::compr::DecompressError;
13 //! use nihav_core::compr::deflate::Inflate;
15 //! # fn decompress(input: &[u8]) -> Result<(), DecompressError> {
16 //! # let mut output_buffer = [0u8; 16];
17 //! let output_length = Inflate::uncompress(input, &mut output_buffer)?;
22 //! Decompressing input chunks into portions of output:
24 //! use nihav_core::compr::DecompressError;
25 //! use nihav_core::compr::deflate::Inflate;
27 //! # fn decompress(input_data: &[u8]) -> Result<(), DecompressError> {
28 //! let mut inflate = Inflate::new();
29 //! let mut dst_buf: Vec<u8> = Vec::new();
30 //! let mut output_chunk = [0u8; 1024];
31 //! for src in input_data.chunks(512) {
32 //! let mut repeat = false;
34 //! let ret = inflate.decompress_data(src, &mut output_chunk, repeat);
36 //! Ok(len) => { // we got a buffer decoded successfully to the end
37 //! dst_buf.extend_from_slice(&output_chunk[..len]);
40 //! Err(DecompressError::ShortData) => { // this block of data was fully read
43 //! Err(DecompressError::OutputFull) => {
44 //! // the output buffer is full, flush it and continue decoding the same block
46 //! dst_buf.extend_from_slice(&output_chunk);
58 use crate::io::byteio::*;
59 use crate::io::bitreader::*;
60 use crate::io::codebook::*;
63 const NUM_LITERALS: usize = 287;
64 const NUM_DISTS: usize = 32;
66 struct FixedLenCodeReader {}
68 impl CodebookDescReader<u16> for FixedLenCodeReader {
69 fn bits(&mut self, idx: usize) -> u8 {
71 else if idx < 256 { 9 }
72 else if idx < 280 { 7 }
75 #[allow(clippy::identity_op)]
76 fn code(&mut self, idx: usize) -> u32 {
77 let base = idx as u32;
78 let bits = self.bits(idx);
79 if idx < 144 { reverse_bits(base + 0x30, bits) }
80 else if idx < 256 { reverse_bits(base + 0x190 - 144, bits) }
81 else if idx < 280 { reverse_bits(base + 0x000 - 256, bits) }
82 else { reverse_bits(base + 0xC0 - 280, bits) }
84 fn sym (&mut self, idx: usize) -> u16 { idx as u16 }
85 fn len(&mut self) -> usize { NUM_LITERALS + 1 }
88 #[derive(Clone,Copy,Default)]
89 struct BitReaderState {
95 struct CurrentSource<'a> {
100 impl<'a> CurrentSource<'a> {
101 fn new(src: &'a [u8], br: BitReaderState) -> Self {
102 let mut newsrc = Self { src, br };
107 fn reinit(src: &'a [u8], br: BitReaderState) -> Self {
108 let mut newsrc = Self { src, br };
112 fn refill(&mut self) {
113 while (self.br.bits <= 24) && (self.br.pos < self.src.len()) {
114 self.br.bitbuf |= u32::from(self.src[self.br.pos]) << self.br.bits;
119 fn skip_cache(&mut self, nbits: u8) {
120 self.br.bitbuf >>= nbits;
121 self.br.bits -= nbits;
123 fn read(&mut self, nbits: u8) -> BitReaderResult<u32> {
124 if nbits == 0 { return Ok(0); }
125 if nbits > 16 { return Err(BitReaderError::TooManyBitsRequested); }
126 if self.br.bits < nbits {
128 if self.br.bits < nbits { return Err(BitReaderError::BitstreamEnd); }
130 let ret = self.br.bitbuf & ((1 << nbits) - 1);
131 self.skip_cache(nbits);
134 fn read_bool(&mut self) -> BitReaderResult<bool> {
135 if self.br.bits == 0 {
137 if self.br.bits == 0 { return Err(BitReaderError::BitstreamEnd); }
139 let ret = (self.br.bitbuf & 1) != 0;
143 fn peek(&mut self, nbits: u8) -> u32 {
144 if nbits == 0 || nbits > 16 { return 0; }
145 if self.br.bits < nbits {
148 self.br.bitbuf & ((1 << nbits) - 1)
150 fn skip(&mut self, nbits: u32) -> BitReaderResult<()> {
151 if u32::from(self.br.bits) >= nbits {
152 self.skip_cache(nbits as u8);
158 fn align(&mut self) {
159 let b = self.br.bits & 7;
161 self.skip_cache(8 - (b as u8));
164 fn left(&self) -> isize {
165 ((self.src.len() as isize) - (self.br.pos as isize)) * 8 + (self.br.bits as isize)
169 impl<'a, S: Copy> CodebookReader<S> for CurrentSource<'a> {
170 fn read_cb(&mut self, cb: &Codebook<S>) -> CodebookResult<S> {
173 let mut lut_bits = cb.lut_bits;
174 let orig_br = self.br;
176 let lut_idx = (self.peek(lut_bits) as usize) + (idx as usize);
177 if cb.table[lut_idx] == TABLE_FILL_VALUE { return Err(CodebookError::InvalidCode); }
178 let bits = cb.table[lut_idx] & 0x7F;
179 esc = (cb.table[lut_idx] & 0x80) != 0;
180 idx = (cb.table[lut_idx] >> 8) as usize;
181 let skip_bits = if esc { u32::from(lut_bits) } else { bits };
182 if (skip_bits as isize) > self.left() {
185 return Err(CodebookError::MemoryError);
187 self.skip(skip_bits as u32).unwrap();
188 lut_bits = bits as u8;
199 StaticBlockInvLen(u32),
200 StaticBlockCopy(usize),
202 FixedBlockLengthExt(usize, u8),
203 FixedBlockDist(usize),
204 FixedBlockDistExt(usize, usize, u8),
205 FixedBlockCopy(usize, usize),
206 FixedBlockLiteral(u8),
212 DynCodeLengthsAdd(usize),
214 DynBlockLengthExt(usize, u8),
216 DynBlockDistExt(usize, usize, u8),
217 DynCopy(usize, usize),
222 ///! The decompressor for deflated streams (RFC 1951).
225 fix_len_cb: Codebook<u16>,
236 dyn_len_cb: Option<Codebook<u32>>,
237 dyn_lit_cb: Option<Codebook<u32>>,
238 dyn_dist_cb: Option<Codebook<u32>>,
239 len_lengths: [u8; 19],
240 all_lengths: [u8; NUM_LITERALS + NUM_DISTS],
244 const LENGTH_ADD_BITS: [u8; 29] = [
245 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
246 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
247 4, 4, 4, 4, 5, 5, 5, 5, 0
249 const LENGTH_BASE: [u16; 29] = [
250 3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
251 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
252 67, 83, 99, 115, 131, 163, 195, 227, 258
254 const DIST_ADD_BITS: [u8; 30] = [
255 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
256 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
257 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
259 const DIST_BASE: [u16; 30] = [
260 1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
261 33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
262 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
264 const LEN_RECODE: [usize; 19] = [
265 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
267 const REPEAT_BITS: [u8; 3] = [ 2, 3, 7 ];
268 const REPEAT_BASE: [u8; 3] = [ 3, 3, 11 ];
270 macro_rules! read_bits {
271 ($self: expr, $csrc: expr, $bits: expr) => ({
272 if $csrc.left() < $bits as isize {
274 return Err(DecompressError::ShortData);
276 $csrc.read($bits).unwrap()
280 macro_rules! read_cb {
281 ($self: expr, $csrc: expr, $cb: expr) => ({
282 let ret = $csrc.read_cb($cb);
283 if let Err(CodebookError::MemoryError) = ret {
285 return Err(DecompressError::ShortData);
290 $self.state = InflateState::End;
291 return Err(DecompressError::InvalidData);
298 ///! Creates a new instance of `Inflate` struct.
299 pub fn new() -> Self {
300 let mut cr = FixedLenCodeReader {};
301 let fix_len_cb = Codebook::new(&mut cr, CodebookMode::LSB).unwrap();
303 br: BitReaderState::default(),
311 state: InflateState::Start,
318 len_lengths: [0; 19],
319 all_lengths: [0; NUM_LITERALS + NUM_DISTS],
323 fn put_literal(&mut self, val: u8) {
324 self.buf[self.bpos] = val;
325 self.bpos = (self.bpos + 1) & (self.buf.len() - 1);
328 fn lz_copy(&mut self, offset: usize, len: usize, dst: &mut [u8]) -> DecompressResult<()> {
329 let mask = self.buf.len() - 1;
330 if offset > self.full_pos {
331 return Err(DecompressError::InvalidData);
333 let cstart = (self.bpos.wrapping_sub(offset)) & mask;
335 self.buf[(self.bpos + i) & mask] = self.buf[(cstart + i) & mask];
336 dst[i] = self.buf[(cstart + i) & mask];
338 self.bpos = (self.bpos + len) & mask;
339 self.full_pos += len;
342 ///! Reports whether decoder has finished decoding the input.
343 pub fn is_finished(&self) -> bool {
345 InflateState::End => true,
349 ///! Reports the current amount of bytes output into the destination buffer after the last run.
350 pub fn get_current_output_size(&self) -> usize { self.output_idx }
351 ///! Reports the total amount of bytes decoded so far.
352 pub fn get_total_output_size(&self) -> usize { self.bpos }
353 ///! Tries to decompress input data and write it to the output buffer.
355 ///! Since the decompressor can work with arbitrary input and output chunks its return value may have several meanings:
356 ///! * `Ok(len)` means the stream has been fully decoded and then number of bytes output into the destination buffer is returned.
357 ///! * [`DecompressError::ShortData`] means the input stream has been fully read but more data is needed.
358 ///! * [`DecompressError::OutputFull`] means the output buffer is full and should be flushed. Then decoding should continue on the same input block with `continue_block` parameter set to `true`.
360 ///! [`DecompressError::ShortData`]: ../enum.DecompressError.html#variant.ShortData
361 ///! [`DecompressError::OutputFull`]: ../enum.DecompressError.html#variant.OutputFull
362 pub fn decompress_data(&mut self, src: &[u8], dst: &mut [u8], continue_block: bool) -> DecompressResult<usize> {
363 if src.is_empty() || dst.is_empty() {
364 return Err(DecompressError::InvalidArgument);
366 let mut csrc = if !continue_block {
367 CurrentSource::new(src, self.br)
370 CurrentSource::reinit(src, self.br)
374 InflateState::Start | InflateState::BlockStart => {
375 if csrc.left() == 0 {
377 return Err(DecompressError::ShortData);
379 self.final_block = csrc.read_bool().unwrap();
380 self.state = InflateState::BlockMode;
382 InflateState::BlockMode => {
383 let bmode = read_bits!(self, csrc, 2);
387 self.state = InflateState::StaticBlockLen;
389 1 => { self.state = InflateState::FixedBlock; },
390 2 => { self.state = InflateState::DynBlockHlit; },
392 self.state = InflateState::End;
393 return Err(DecompressError::InvalidHeader);
397 InflateState::StaticBlockLen => {
398 let len = read_bits!(self, csrc, 16);
399 self.state = InflateState::StaticBlockInvLen(len);
401 InflateState::StaticBlockInvLen(len) => {
402 let inv_len = read_bits!(self, csrc, 16);
404 self.state = InflateState::End;
405 return Err(DecompressError::InvalidHeader);
407 self.state = InflateState::StaticBlockCopy(len as usize);
409 InflateState::StaticBlockCopy(len) => {
413 self.state = InflateState::StaticBlockCopy(len - i);
414 return Err(DecompressError::ShortData);
416 let val = csrc.read(8).unwrap() as u8;
417 self.put_literal(val);
419 self.state = InflateState::BlockStart;
421 InflateState::FixedBlock => {
422 let val = read_cb!(self, csrc, &self.fix_len_cb);
424 if self.output_idx >= dst.len() {
426 self.state = InflateState::FixedBlockLiteral(val as u8);
427 return Err(DecompressError::OutputFull);
429 self.put_literal(val as u8);
430 dst[self.output_idx] = val as u8;
431 self.output_idx += 1;
432 } else if val == 256 {
433 if self.final_block {
434 self.state = InflateState::End;
435 return Ok(self.output_idx);
437 self.state = InflateState::BlockStart;
440 let len_idx = (val - 257) as usize;
441 if len_idx >= LENGTH_BASE.len() {
442 self.state = InflateState::End;
443 return Err(DecompressError::InvalidData);
445 let len_bits = LENGTH_ADD_BITS[len_idx];
446 let add_base = LENGTH_BASE[len_idx] as usize;
448 self.state = InflateState::FixedBlockLengthExt(add_base, len_bits);
450 self.state = InflateState::FixedBlockDist(add_base);
454 InflateState::FixedBlockLiteral(sym) => {
455 if self.output_idx >= dst.len() {
457 return Err(DecompressError::OutputFull);
459 self.put_literal(sym);
460 dst[self.output_idx] = sym;
461 self.output_idx += 1;
462 self.state = InflateState::FixedBlock;
464 InflateState::FixedBlockLengthExt(base, bits) => {
465 let add = read_bits!(self, csrc, bits) as usize;
466 self.state = InflateState::FixedBlockDist(base + add);
468 InflateState::FixedBlockDist(length) => {
469 let dist_idx = reverse_bits(read_bits!(self, csrc, 5), 5) as usize;
470 if dist_idx >= DIST_BASE.len() {
471 self.state = InflateState::End;
472 return Err(DecompressError::InvalidData);
474 let dist_bits = DIST_ADD_BITS[dist_idx];
475 let dist_base = DIST_BASE[dist_idx] as usize;
477 self.state = InflateState::FixedBlockCopy(length, dist_base);
479 self.state = InflateState::FixedBlockDistExt(length, dist_base, dist_bits);
482 InflateState::FixedBlockDistExt(length, base, bits) => {
483 let add = read_bits!(self, csrc, bits) as usize;
484 self.state = InflateState::FixedBlockCopy(length, base + add);
486 InflateState::FixedBlockCopy(length, dist) => {
487 if self.output_idx + length > dst.len() {
488 let copy_size = dst.len() - self.output_idx;
489 let ret = self.lz_copy(dist, copy_size, &mut dst[self.output_idx..]);
491 self.state = InflateState::End;
492 return Err(DecompressError::InvalidData);
494 self.output_idx += copy_size;
496 self.state = InflateState::FixedBlockCopy(length - copy_size, dist);
497 return Err(DecompressError::OutputFull);
499 let ret = self.lz_copy(dist, length, &mut dst[self.output_idx..]);
501 self.state = InflateState::End;
502 return Err(DecompressError::InvalidData);
504 self.output_idx += length;
505 self.state = InflateState::FixedBlock;
507 InflateState::DynBlockHlit => {
508 self.hlit = (read_bits!(self, csrc, 5) as usize) + 257;
509 if self.hlit >= 287 {
510 self.state = InflateState::End;
511 return Err(DecompressError::InvalidHeader);
513 self.state = InflateState::DynBlockHdist;
515 InflateState::DynBlockHdist => {
516 self.hdist = (read_bits!(self, csrc, 5) as usize) + 1;
517 self.state = InflateState::DynBlockHclen;
519 InflateState::DynBlockHclen => {
520 let hclen = (read_bits!(self, csrc, 4) as usize) + 4;
521 self.cur_len_idx = 0;
522 self.len_lengths = [0; 19];
523 self.all_lengths = [0; NUM_LITERALS + NUM_DISTS];
524 self.state = InflateState::DynLengths(hclen);
526 InflateState::DynLengths(len) => {
530 self.state = InflateState::DynLengths(len - i);
531 return Err(DecompressError::ShortData);
533 self.len_lengths[LEN_RECODE[self.cur_len_idx]] = csrc.read(3).unwrap() as u8;
534 self.cur_len_idx += 1;
536 let mut len_codes = [ShortCodebookDesc { code: 0, bits: 0 }; 19];
537 lengths_to_codes(&self.len_lengths, &mut len_codes)?;
538 let mut cr = ShortCodebookDescReader::new(len_codes.to_vec());
539 let ret = Codebook::new(&mut cr, CodebookMode::LSB);
541 self.state = InflateState::End;
542 return Err(DecompressError::InvalidHeader);
544 self.dyn_len_cb = Some(ret.unwrap());
545 self.cur_len_idx = 0;
546 self.state = InflateState::DynCodeLengths;
548 InflateState::DynCodeLengths => {
549 if let Some(ref len_cb) = self.dyn_len_cb {
550 while self.cur_len_idx < self.hlit + self.hdist {
551 let ret = csrc.read_cb(len_cb);
552 let val = match ret {
554 Err(CodebookError::MemoryError) => {
556 return Err(DecompressError::ShortData);
559 self.state = InflateState::End;
560 return Err(DecompressError::InvalidHeader);
564 self.all_lengths[self.cur_len_idx] = val as u8;
565 self.cur_len_idx += 1;
567 let idx = (val as usize) - 16;
569 self.state = InflateState::End;
570 return Err(DecompressError::InvalidHeader);
572 self.state = InflateState::DynCodeLengthsAdd(idx);
576 let (lit_lengths, dist_lengths) = self.all_lengths.split_at(self.hlit);
578 let mut lit_codes = [ShortCodebookDesc { code: 0, bits: 0 }; NUM_LITERALS];
579 lengths_to_codes(&lit_lengths, &mut lit_codes)?;
580 let mut cr = ShortCodebookDescReader::new(lit_codes.to_vec());
581 let ret = Codebook::new(&mut cr, CodebookMode::LSB);
582 if ret.is_err() { return Err(DecompressError::InvalidHeader); }
583 self.dyn_lit_cb = Some(ret.unwrap());
585 let mut dist_codes = [ShortCodebookDesc { code: 0, bits: 0 }; NUM_DISTS];
586 lengths_to_codes(&dist_lengths[..self.hdist], &mut dist_codes)?;
587 let mut cr = ShortCodebookDescReader::new(dist_codes.to_vec());
588 let ret = Codebook::new(&mut cr, CodebookMode::LSB);
589 if ret.is_err() { return Err(DecompressError::InvalidHeader); }
590 self.dyn_dist_cb = Some(ret.unwrap());
592 self.state = InflateState::DynBlock;
597 InflateState::DynCodeLengthsAdd(mode) => {
598 let base = REPEAT_BASE[mode] as usize;
599 let bits = REPEAT_BITS[mode];
600 let len = base + read_bits!(self, csrc, bits) as usize;
601 if self.cur_len_idx + len > self.hlit + self.hdist {
602 self.state = InflateState::End;
603 return Err(DecompressError::InvalidHeader);
605 let rpt = if mode == 0 {
606 if self.cur_len_idx == 0 {
607 self.state = InflateState::End;
608 return Err(DecompressError::InvalidHeader);
610 self.all_lengths[self.cur_len_idx - 1]
615 self.all_lengths[self.cur_len_idx] = rpt;
616 self.cur_len_idx += 1;
618 self.state = InflateState::DynCodeLengths;
620 InflateState::DynBlock => {
621 if let Some(ref lit_cb) = self.dyn_lit_cb {
622 let val = read_cb!(self, csrc, lit_cb);
624 if self.output_idx >= dst.len() {
626 self.state = InflateState::DynBlockLiteral(val as u8);
627 return Err(DecompressError::OutputFull);
629 self.put_literal(val as u8);
630 dst[self.output_idx] = val as u8;
631 self.output_idx += 1;
632 } else if val == 256 {
633 if self.final_block {
634 self.state = InflateState::End;
635 return Ok(self.output_idx);
637 self.state = InflateState::BlockStart;
640 let len_idx = (val - 257) as usize;
641 if len_idx >= LENGTH_BASE.len() {
642 self.state = InflateState::End;
643 return Err(DecompressError::InvalidData);
645 let len_bits = LENGTH_ADD_BITS[len_idx];
646 let add_base = LENGTH_BASE[len_idx] as usize;
648 self.state = InflateState::DynBlockLengthExt(add_base, len_bits);
650 self.state = InflateState::DynBlockDist(add_base);
657 InflateState::DynBlockLiteral(sym) => {
658 if self.output_idx >= dst.len() {
660 return Err(DecompressError::OutputFull);
662 self.put_literal(sym);
663 dst[self.output_idx] = sym;
664 self.output_idx += 1;
665 self.state = InflateState::DynBlock;
667 InflateState::DynBlockLengthExt(base, bits) => {
668 let add = read_bits!(self, csrc, bits) as usize;
669 self.state = InflateState::DynBlockDist(base + add);
671 InflateState::DynBlockDist(length) => {
672 if let Some(ref dist_cb) = self.dyn_dist_cb {
673 let dist_idx = read_cb!(self, csrc, dist_cb) as usize;
674 if dist_idx >= DIST_BASE.len() {
675 self.state = InflateState::End;
676 return Err(DecompressError::InvalidData);
678 let dist_bits = DIST_ADD_BITS[dist_idx];
679 let dist_base = DIST_BASE[dist_idx] as usize;
681 self.state = InflateState::DynCopy(length, dist_base);
683 self.state = InflateState::DynBlockDistExt(length, dist_base, dist_bits);
689 InflateState::DynBlockDistExt(length, base, bits) => {
690 let add = read_bits!(self, csrc, bits) as usize;
691 self.state = InflateState::DynCopy(length, base + add);
693 InflateState::DynCopy(length, dist) => {
694 if self.output_idx + length > dst.len() {
695 let copy_size = dst.len() - self.output_idx;
696 let ret = self.lz_copy(dist, copy_size, &mut dst[self.output_idx..]);
698 self.state = InflateState::End;
699 return Err(DecompressError::InvalidData);
701 self.output_idx += copy_size;
703 self.state = InflateState::DynCopy(length - copy_size, dist);
704 return Err(DecompressError::OutputFull);
706 let ret = self.lz_copy(dist, length, &mut dst[self.output_idx..]);
708 self.state = InflateState::End;
709 return Err(DecompressError::InvalidData);
711 self.output_idx += length;
712 self.state = InflateState::DynBlock;
714 InflateState::End => {
720 ///! Decompresses input data into output returning the uncompressed data length.
721 pub fn uncompress(src: &[u8], dst: &mut [u8]) -> DecompressResult<usize> {
722 let mut inflate = Self::new();
723 let off = if src.len() > 2 && src[0] == 0x78 && src[1] == 0x9C { 2 } else { 0 };
724 inflate.decompress_data(&src[off..], dst, false)
728 impl Default for Inflate {
729 fn default() -> Self {
734 fn lengths_to_codes(lens: &[u8], codes: &mut [ShortCodebookDesc]) -> DecompressResult<()> {
735 let mut bits = [0u32; 32];
736 let mut pfx = [0u32; 33];
737 for len in lens.iter() {
738 let len = *len as usize;
739 if len >= bits.len() {
740 return Err(DecompressError::InvalidHeader);
746 for i in 0..bits.len() {
747 code = (code + bits[i]) << 1;
751 for (len, codes) in lens.iter().zip(codes.iter_mut()) {
752 let len = *len as usize;
754 let bits = len as u8;
755 *codes = ShortCodebookDesc { code: reverse_bits(pfx[len], bits), bits };
758 *codes = ShortCodebookDesc { code: 0, bits: 0 };
771 #[allow(clippy::unreadable_literal)]
773 let mut tab = [0u32; 256];
775 let mut c = i as u32;
778 c = 0xEDB88320 ^ (c >> 1);
787 fn update_crc(&mut self, src: &[u8]) {
788 let mut c = !self.crc;
789 for el in src.iter() {
790 c = self.tab[((c ^ u32::from(*el)) & 0xFF) as usize] ^ (c >> 8);
796 ///! Decodes input data in gzip file format (RFC 1952) returning a vector containing decoded data.
797 pub fn gzip_decode(br: &mut ByteReader, skip_crc: bool) -> DecompressResult<Vec<u8>> {
798 const FLAG_HCRC: u8 = 0x02;
799 const FLAG_EXTRA: u8 = 0x04;
800 const FLAG_NAME: u8 = 0x08;
801 const FLAG_COMMENT: u8 = 0x10;
803 let id1 = br.read_byte()?;
804 let id2 = br.read_byte()?;
805 let cm = br.read_byte()?;
806 let flg = br.read_byte()?;
807 let _mtime = br.read_u32le()?;
808 let _xfl = br.read_byte()?;
809 let _os = br.read_byte()?;
810 if id1 != 0x1F || id2 != 0x8B || cm != 8 {
811 return Err(DecompressError::InvalidHeader);
814 if (flg & FLAG_EXTRA) != 0 {
815 let xlen = br.read_u16le()? as usize;
818 if (flg & FLAG_NAME) != 0 {
820 let b = br.read_byte()?;
826 if (flg & FLAG_COMMENT) != 0 {
828 let b = br.read_byte()?;
834 let _hcrc = if (flg & FLAG_HCRC) != 0 {
839 if (flg & 0xE0) != 0 {
840 return Err(DecompressError::Unsupported);
843 let mut output: Vec<u8> = Vec::new();
844 let mut tail = [0u8; 8];
845 let mut inblk = [0u8; 1024];
846 let mut oblk = [0u8; 4096];
847 let mut inflate = Inflate::new();
848 let mut checker = GzipCRC32::new();
851 let ret = br.read_buf_some(&mut inblk);
852 if let Err(ByteIOError::EOF) = ret {
855 let inlen = match ret {
857 Err(_) => return Err(DecompressError::IOError),
859 let mut repeat = false;
861 let ret = inflate.decompress_data(&inblk[..inlen], &mut oblk, repeat);
864 checker.update_crc(&oblk[..outlen]);
865 output.extend_from_slice(&oblk[..outlen]);
868 Err(DecompressError::ShortData) => {
871 Err(DecompressError::OutputFull) => {
873 checker.update_crc(&oblk);
874 output.extend_from_slice(&oblk);
881 // Save last 8 bytes for CRC and size.
883 tail.copy_from_slice(&inblk[inlen - 8..][..8]);
885 let shift_len = 8 - inlen;
886 for i in 0..shift_len {
887 tail[i] = tail[i + inlen];
889 for i in shift_len..8 {
890 tail[i] = inblk[i - shift_len];
895 if !inflate.is_finished() { println!("???"); }
896 let crc = read_u32le(&tail[0..4])?;
897 let size = read_u32le(&tail[4..8])?;
898 if size != (output.len() as u32) {
899 return Err(DecompressError::CRCError);
901 if crc != checker.crc {
902 return Err(DecompressError::CRCError);
915 const TEST_DATA: &[u8] = &[
916 0xF3, 0x48, 0xCD, 0xC9, 0xC9, 0xD7, 0x51, 0x28,
917 0xCF, 0x2F, 0xCA, 0x49, 0x51, 0x04, 0x00 ];
918 const TEST_REF: &[u8] = b"Hello, world!";
919 let mut dst_buf = [0u8; 13];
920 let len = Inflate::uncompress(TEST_DATA, &mut dst_buf).unwrap();
923 assert_eq!(dst_buf[i], TEST_REF[i]);
928 const TEST_DATA3: &[u8] = &[ 0x4B, 0x4C, 0x44, 0x80, 0x24, 0x54, 0x80, 0x2C, 0x06, 0x00 ];
929 const TEST_REF3: &[u8] = b"aaaaaaaaaaaabbbbbbbbbbbbbbbaaaaabbbbbbb";
930 let mut dst_buf = [0u8; 39];
932 let mut inflate = Inflate::new();
933 let mut output_chunk = [0u8; 7];
934 let mut output_pos = 0;
935 for input in TEST_DATA3.chunks(3) {
936 let mut repeat = false;
938 let ret = inflate.decompress_data(input, &mut output_chunk, repeat);
942 dst_buf[output_pos + i] = output_chunk[i];
947 Err(DecompressError::ShortData) => {
950 Err(DecompressError::OutputFull) => {
952 for i in 0..output_chunk.len() {
953 dst_buf[output_pos + i] = output_chunk[i];
955 output_pos += output_chunk.len();
958 panic!("decompress error {:?}", ret.err().unwrap());
964 assert_eq!(output_pos, dst_buf.len());
965 for i in 0..output_pos {
966 assert_eq!(dst_buf[i], TEST_REF3[i]);
971 const TEST_DATA: &[u8] = &[
972 0x1F, 0x8B, 0x08, 0x08, 0xF6, 0x7B, 0x90, 0x5E, 0x02, 0x03, 0x31, 0x2E, 0x74, 0x78, 0x74, 0x00,
973 0xE5, 0x95, 0x4B, 0x4E, 0xC3, 0x30, 0x10, 0x40, 0xF7, 0x39, 0xC5, 0x1C, 0x00, 0x16, 0x70, 0x83,
974 0x0A, 0xB5, 0x3B, 0xE8, 0x82, 0x5E, 0x60, 0x1A, 0x4F, 0xE2, 0x11, 0xFE, 0x44, 0x1E, 0xA7, 0x69,
975 0x6E, 0xCF, 0x38, 0xDD, 0xB0, 0x40, 0xA2, 0x46, 0x2D, 0x20, 0x2A, 0xE5, 0xAB, 0xCC, 0xE7, 0xBD,
976 0x49, 0xAC, 0x6C, 0x03, 0x64, 0x4B, 0xD0, 0x71, 0x92, 0x0C, 0x06, 0x67, 0x88, 0x1D, 0x3C, 0xD9,
977 0xC4, 0x92, 0x3D, 0x4A, 0xF3, 0x3C, 0x43, 0x4E, 0x23, 0x81, 0x8B, 0x07, 0x82, 0x1E, 0xF5, 0x90,
978 0x23, 0x78, 0x6A, 0x56, 0x30, 0x60, 0xCA, 0x89, 0x4D, 0x4F, 0xC0, 0x01, 0x10, 0x06, 0xC2, 0xA4,
979 0xA1, 0x44, 0xCD, 0xF6, 0x54, 0x50, 0xA8, 0x8D, 0xC1, 0x9C, 0x5F, 0x71, 0x37, 0x45, 0xC8, 0x63,
980 0xCA, 0x8E, 0xC0, 0xE8, 0x23, 0x69, 0x56, 0x9A, 0x8D, 0x5F, 0xB6, 0xC9, 0x96, 0x53, 0x4D, 0x17,
981 0xAB, 0xB9, 0xB0, 0x49, 0x14, 0x5A, 0x0B, 0x96, 0x82, 0x7C, 0xB7, 0x6F, 0x17, 0x35, 0xC7, 0x9E,
982 0xDF, 0x78, 0xA3, 0xF1, 0xD0, 0xA2, 0x73, 0x1C, 0x7A, 0xD8, 0x2B, 0xB3, 0x5C, 0x90, 0x85, 0xBB,
983 0x2A, 0x14, 0x2E, 0xF7, 0xD1, 0x19, 0x48, 0x0A, 0x23, 0x57, 0x45, 0x13, 0x3E, 0xD6, 0xA0, 0xBD,
984 0xF2, 0x11, 0x7A, 0x22, 0x21, 0xAD, 0xE5, 0x70, 0x56, 0xA0, 0x9F, 0xA5, 0xA5, 0x03, 0x85, 0x2A,
985 0xDE, 0x92, 0x00, 0x32, 0x61, 0x10, 0xAD, 0x27, 0x13, 0x7B, 0x5F, 0x98, 0x7F, 0x59, 0x83, 0xB8,
986 0xB7, 0x35, 0x16, 0xEB, 0x12, 0x0F, 0x1E, 0xD9, 0x14, 0x0B, 0xCF, 0xEE, 0x6D, 0x91, 0xF8, 0x93,
987 0x6E, 0x81, 0x3F, 0x7F, 0x41, 0xA4, 0x22, 0x1F, 0xB7, 0xE6, 0x85, 0x83, 0x9A, 0xA2, 0x61, 0x12,
988 0x0D, 0x0F, 0x6D, 0x01, 0xBD, 0xB0, 0xE8, 0x1D, 0xEC, 0xD1, 0xA0, 0xBF, 0x1F, 0x4E, 0xFB, 0x55,
989 0xBD, 0x73, 0xDD, 0x87, 0xB9, 0x53, 0x23, 0x17, 0xD3, 0xE2, 0xE9, 0x08, 0x87, 0x42, 0xFF, 0xCF,
990 0x26, 0x42, 0xAE, 0x76, 0xB5, 0xAE, 0x97, 0x0C, 0x18, 0x78, 0xA0, 0x24, 0xE5, 0x54, 0x0C, 0x6E,
991 0x60, 0x52, 0x79, 0x22, 0x57, 0xF5, 0x87, 0x78, 0x78, 0x04, 0x93, 0x46, 0xEF, 0xCB, 0x98, 0x96,
992 0x8B, 0x65, 0x00, 0xB7, 0x36, 0xBD, 0x77, 0xA8, 0xBD, 0x5A, 0xAA, 0x1A, 0x09, 0x00, 0x00
995 let mut mr = MemoryReader::new_read(TEST_DATA);
996 let mut br = ByteReader::new(&mut mr);
997 let _dst_buf = gzip_decode(&mut br, false).unwrap();
999 // println!("{}", String::from_utf8_lossy(_dst_buf.as_slice()));