1 //! The encoder and decoder of the GZIP format.
2 //!
3 //! The GZIP format is defined in [RFC-1952](https://tools.ietf.org/html/rfc1952).
4 //!
5 //! # Examples
6 //! ```
7 //! use std::io::{self, Read};
8 //! use libflate::gzip::{Encoder, Decoder};
9 //!
10 //! // Encoding
11 //! let mut encoder = Encoder::new(Vec::new()).unwrap();
12 //! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap();
13 //! let encoded_data = encoder.finish().into_result().unwrap();
14 //!
15 //! // Decoding
16 //! let mut decoder = Decoder::new(&encoded_data[..]).unwrap();
17 //! let mut decoded_data = Vec::new();
18 //! decoder.read_to_end(&mut decoded_data).unwrap();
19 //!
20 //! assert_eq!(decoded_data, b"Hello World!");
21 //! ```
22 use crate::checksum;
23 use crate::deflate;
24 use crate::finish::{Complete, Finish};
25 use crate::lz77;
26 use std::{ffi::CString, io, time};
27
28 const GZIP_ID: [u8; 2] = [31, 139];
29 const COMPRESSION_METHOD_DEFLATE: u8 = 8;
30
31 const OS_FAT: u8 = 0;
32 const OS_AMIGA: u8 = 1;
33 const OS_VMS: u8 = 2;
34 const OS_UNIX: u8 = 3;
35 const OS_VM_CMS: u8 = 4;
36 const OS_ATARI_TOS: u8 = 5;
37 const OS_HPFS: u8 = 6;
38 const OS_MACINTOSH: u8 = 7;
39 const OS_Z_SYSTEM: u8 = 8;
40 const OS_CPM: u8 = 9;
41 const OS_TOPS20: u8 = 10;
42 const OS_NTFS: u8 = 11;
43 const OS_QDOS: u8 = 12;
44 const OS_ACORN_RISCOS: u8 = 13;
45 const OS_UNKNOWN: u8 = 255;
46
47 const F_TEXT: u8 = 0b00_0001;
48 const F_HCRC: u8 = 0b00_0010;
49 const F_EXTRA: u8 = 0b00_0100;
50 const F_NAME: u8 = 0b00_1000;
51 const F_COMMENT: u8 = 0b01_0000;
52
53 /// Compression levels defined by the GZIP format.
54 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
55 pub enum CompressionLevel {
56 /// Compressor used fastest algorithm.
57 Fastest,
58
59 /// Compressor used maximum compression, slowest algorithm.
60 Slowest,
61
62 /// No information about compression method.
63 Unknown,
64 }
65 impl CompressionLevel {
to_u8(&self) -> u866 fn to_u8(&self) -> u8 {
67 match *self {
68 CompressionLevel::Fastest => 4,
69 CompressionLevel::Slowest => 2,
70 CompressionLevel::Unknown => 0,
71 }
72 }
from_u8(x: u8) -> Self73 fn from_u8(x: u8) -> Self {
74 match x {
75 4 => CompressionLevel::Fastest,
76 2 => CompressionLevel::Slowest,
77 _ => CompressionLevel::Unknown,
78 }
79 }
80 }
81 impl From<lz77::CompressionLevel> for CompressionLevel {
from(f: lz77::CompressionLevel) -> Self82 fn from(f: lz77::CompressionLevel) -> Self {
83 match f {
84 lz77::CompressionLevel::Fast => CompressionLevel::Fastest,
85 lz77::CompressionLevel::Best => CompressionLevel::Slowest,
86 _ => CompressionLevel::Unknown,
87 }
88 }
89 }
90
91 #[derive(Debug, Clone)]
92 pub(crate) struct Trailer {
93 crc32: u32,
94 input_size: u32,
95 }
96 impl Trailer {
crc32(&self) -> u3297 pub fn crc32(&self) -> u32 {
98 self.crc32
99 }
read_from<R>(mut reader: R) -> io::Result<Self> where R: io::Read,100 pub fn read_from<R>(mut reader: R) -> io::Result<Self>
101 where
102 R: io::Read,
103 {
104 let mut buf = [0; 4];
105 reader.read_exact(&mut buf)?;
106 let crc32 = u32::from_le_bytes(buf);
107 reader.read_exact(&mut buf)?;
108 let input_size = u32::from_le_bytes(buf);
109 Ok(Trailer { crc32, input_size })
110 }
write_to<W>(&self, mut writer: W) -> io::Result<()> where W: io::Write,111 fn write_to<W>(&self, mut writer: W) -> io::Result<()>
112 where
113 W: io::Write,
114 {
115 writer.write_all(&self.crc32.to_le_bytes())?;
116 writer.write_all(&self.input_size.to_le_bytes())?;
117 Ok(())
118 }
119 }
120
121 /// GZIP header builder.
122 #[derive(Debug, Clone)]
123 pub struct HeaderBuilder {
124 header: Header,
125 }
126 impl HeaderBuilder {
127 /// Makes a new builder instance.
128 ///
129 /// # Examples
130 /// ```
131 /// use libflate::gzip::{HeaderBuilder, CompressionLevel, Os};
132 ///
133 /// let header = HeaderBuilder::new().finish();
134 /// assert_eq!(header.compression_level(), CompressionLevel::Unknown);
135 /// assert_eq!(header.os(), Os::Unix);
136 /// assert_eq!(header.is_text(), false);
137 /// assert_eq!(header.is_verified(), false);
138 /// assert_eq!(header.extra_field(), None);
139 /// assert_eq!(header.filename(), None);
140 /// assert_eq!(header.comment(), None);
141 /// ```
new() -> Self142 pub fn new() -> Self {
143 // wasm-unknown-unknown does not implement the time module
144 #[cfg(not(target_arch = "wasm32"))]
145 let modification_time = time::UNIX_EPOCH
146 .elapsed()
147 .map(|d| d.as_secs() as u32)
148 .unwrap_or(0);
149 #[cfg(target_arch = "wasm32")]
150 let modification_time = 0;
151
152 let header = Header {
153 modification_time,
154 compression_level: CompressionLevel::Unknown,
155 os: Os::Unix,
156 is_text: false,
157 is_verified: false,
158 extra_field: None,
159 filename: None,
160 comment: None,
161 };
162 HeaderBuilder { header }
163 }
164
165 /// Sets the modification time (UNIX timestamp).
166 ///
167 /// # Examples
168 /// ```
169 /// use libflate::gzip::HeaderBuilder;
170 ///
171 /// let header = HeaderBuilder::new().modification_time(10).finish();
172 /// assert_eq!(header.modification_time(), 10);
173 /// ```
modification_time(&mut self, modification_time: u32) -> &mut Self174 pub fn modification_time(&mut self, modification_time: u32) -> &mut Self {
175 self.header.modification_time = modification_time;
176 self
177 }
178
179 /// Sets the OS type.
180 ///
181 /// ```
182 /// use libflate::gzip::{HeaderBuilder, Os};
183 ///
184 /// let header = HeaderBuilder::new().os(Os::Ntfs).finish();
185 /// assert_eq!(header.os(), Os::Ntfs);
186 /// ```
os(&mut self, os: Os) -> &mut Self187 pub fn os(&mut self, os: Os) -> &mut Self {
188 self.header.os = os;
189 self
190 }
191
192 /// Indicates the encoding data is a ASCII text.
193 ///
194 /// # Examples
195 /// ```
196 /// use libflate::gzip::HeaderBuilder;
197 ///
198 /// let header = HeaderBuilder::new().text().finish();
199 /// assert_eq!(header.is_text(), true);
200 /// ```
text(&mut self) -> &mut Self201 pub fn text(&mut self) -> &mut Self {
202 self.header.is_text = true;
203 self
204 }
205
206 /// Specifies toe verify header bytes using CRC-16.
207 ///
208 /// # Examples
209 /// ```
210 /// use libflate::gzip::HeaderBuilder;
211 ///
212 /// let header = HeaderBuilder::new().verify().finish();
213 /// assert_eq!(header.is_verified(), true);
214 /// ```
verify(&mut self) -> &mut Self215 pub fn verify(&mut self) -> &mut Self {
216 self.header.is_verified = true;
217 self
218 }
219
220 /// Sets the extra field.
221 ///
222 /// # Examples
223 /// ```
224 /// use libflate::gzip::{HeaderBuilder, ExtraField, ExtraSubField};
225 ///
226 /// let subfield = ExtraSubField{id: [0, 1], data: vec![2, 3, 4]};
227 /// let extra = ExtraField{subfields: vec![subfield]};
228 /// let header = HeaderBuilder::new().extra_field(extra.clone()).finish();
229 /// assert_eq!(header.extra_field(), Some(&extra));
230 /// ```
extra_field(&mut self, extra: ExtraField) -> &mut Self231 pub fn extra_field(&mut self, extra: ExtraField) -> &mut Self {
232 self.header.extra_field = Some(extra);
233 self
234 }
235
236 /// Sets the file name.
237 ///
238 /// # Examples
239 /// ```
240 /// use std::ffi::CString;
241 /// use libflate::gzip::HeaderBuilder;
242 ///
243 /// let header = HeaderBuilder::new().filename(CString::new("foo").unwrap()).finish();
244 /// assert_eq!(header.filename(), Some(&CString::new("foo").unwrap()));
245 /// ```
filename(&mut self, filename: CString) -> &mut Self246 pub fn filename(&mut self, filename: CString) -> &mut Self {
247 self.header.filename = Some(filename);
248 self
249 }
250
251 /// Sets the comment.
252 ///
253 /// # Examples
254 /// ```
255 /// use std::ffi::CString;
256 /// use libflate::gzip::HeaderBuilder;
257 ///
258 /// let header = HeaderBuilder::new().comment(CString::new("foo").unwrap()).finish();
259 /// assert_eq!(header.comment(), Some(&CString::new("foo").unwrap()));
260 /// ```
comment(&mut self, comment: CString) -> &mut Self261 pub fn comment(&mut self, comment: CString) -> &mut Self {
262 self.header.comment = Some(comment);
263 self
264 }
265
266 /// Returns the result header.
finish(&self) -> Header267 pub fn finish(&self) -> Header {
268 self.header.clone()
269 }
270 }
271 impl Default for HeaderBuilder {
default() -> Self272 fn default() -> Self {
273 Self::new()
274 }
275 }
276
277 /// GZIP Header.
278 #[derive(Debug, Clone)]
279 pub struct Header {
280 modification_time: u32,
281 compression_level: CompressionLevel,
282 os: Os,
283 is_text: bool,
284 is_verified: bool,
285 extra_field: Option<ExtraField>,
286 filename: Option<CString>,
287 comment: Option<CString>,
288 }
289 impl Header {
290 /// Returns the modification time (UNIX timestamp).
modification_time(&self) -> u32291 pub fn modification_time(&self) -> u32 {
292 self.modification_time
293 }
294
295 /// Returns the compression level.
compression_level(&self) -> CompressionLevel296 pub fn compression_level(&self) -> CompressionLevel {
297 self.compression_level.clone()
298 }
299
300 /// Returns the OS type.
os(&self) -> Os301 pub fn os(&self) -> Os {
302 self.os.clone()
303 }
304
305 /// Returns `true` if the stream is probably ASCII text, `false` otherwise.
is_text(&self) -> bool306 pub fn is_text(&self) -> bool {
307 self.is_text
308 }
309
310 /// Returns `true` if the header bytes is verified by CRC-16, `false` otherwise.
is_verified(&self) -> bool311 pub fn is_verified(&self) -> bool {
312 self.is_verified
313 }
314
315 /// Returns the extra field.
extra_field(&self) -> Option<&ExtraField>316 pub fn extra_field(&self) -> Option<&ExtraField> {
317 self.extra_field.as_ref()
318 }
319
320 /// Returns the file name.
filename(&self) -> Option<&CString>321 pub fn filename(&self) -> Option<&CString> {
322 self.filename.as_ref()
323 }
324
325 /// Returns the comment.
comment(&self) -> Option<&CString>326 pub fn comment(&self) -> Option<&CString> {
327 self.comment.as_ref()
328 }
329
flags(&self) -> u8330 fn flags(&self) -> u8 {
331 [
332 (F_TEXT, self.is_text),
333 (F_HCRC, self.is_verified),
334 (F_EXTRA, self.extra_field.is_some()),
335 (F_NAME, self.filename.is_some()),
336 (F_COMMENT, self.comment.is_some()),
337 ]
338 .iter()
339 .filter(|e| e.1)
340 .map(|e| e.0)
341 .sum()
342 }
crc16(&self) -> u16343 fn crc16(&self) -> u16 {
344 let mut crc = checksum::Crc32::new();
345 let mut buf = Vec::new();
346 Header {
347 is_verified: false,
348 ..self.clone()
349 }
350 .write_to(&mut buf)
351 .unwrap();
352 crc.update(&buf);
353 crc.value() as u16
354 }
write_to<W>(&self, mut writer: W) -> io::Result<()> where W: io::Write,355 fn write_to<W>(&self, mut writer: W) -> io::Result<()>
356 where
357 W: io::Write,
358 {
359 writer.write_all(&GZIP_ID)?;
360 writer.write_all(&[COMPRESSION_METHOD_DEFLATE, self.flags()])?;
361 writer.write_all(&self.modification_time.to_le_bytes())?;
362 writer.write_all(&[self.compression_level.to_u8(), self.os.to_u8()])?;
363 if let Some(ref x) = self.extra_field {
364 x.write_to(&mut writer)?;
365 }
366 if let Some(ref x) = self.filename {
367 writer.write_all(x.as_bytes_with_nul())?;
368 }
369 if let Some(ref x) = self.comment {
370 writer.write_all(x.as_bytes_with_nul())?;
371 }
372 if self.is_verified {
373 writer.write_all(&self.crc16().to_le_bytes())?;
374 }
375 Ok(())
376 }
read_from<R>(mut reader: R) -> io::Result<Self> where R: io::Read,377 pub(crate) fn read_from<R>(mut reader: R) -> io::Result<Self>
378 where
379 R: io::Read,
380 {
381 let mut this = HeaderBuilder::new().finish();
382 let mut buf = [0; 2 + 1 + 1 + 4 + 1 + 1];
383 reader.read_exact(&mut buf)?;
384 let id = &buf[0..2];
385 if id != GZIP_ID {
386 return Err(invalid_data_error!(
387 "Unexpected GZIP ID: value={:?}, \
388 expected={:?}",
389 id,
390 GZIP_ID
391 ));
392 }
393 let compression_method = buf[2];
394 if compression_method != COMPRESSION_METHOD_DEFLATE {
395 return Err(invalid_data_error!(
396 "Compression methods other than DEFLATE(8) are \
397 unsupported: method={}",
398 compression_method
399 ));
400 }
401 let flags = buf[3];
402 this.modification_time = u32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]);
403 this.compression_level = CompressionLevel::from_u8(buf[8]);
404 this.os = Os::from_u8(buf[9]);
405 if flags & F_EXTRA != 0 {
406 this.extra_field = Some(ExtraField::read_from(&mut reader)?);
407 }
408 if flags & F_NAME != 0 {
409 this.filename = Some(read_cstring(&mut reader)?);
410 }
411 if flags & F_COMMENT != 0 {
412 this.comment = Some(read_cstring(&mut reader)?);
413 }
414 // Checksum verification is skipped during fuzzing
415 // so that random data from fuzzer can reach actually interesting code.
416 // Compilation flag 'fuzzing' is automatically set by all 3 Rust fuzzers.
417 if flags & F_HCRC != 0 && cfg!(not(fuzzing)) {
418 let mut buf = [0; 2];
419 reader.read_exact(&mut buf)?;
420 let crc = u16::from_le_bytes(buf);
421 let expected = this.crc16();
422 if crc != expected {
423 return Err(invalid_data_error!(
424 "CRC16 of GZIP header mismatched: value={}, \
425 expected={}",
426 crc,
427 expected
428 ));
429 }
430 this.is_verified = true;
431 }
432 Ok(this)
433 }
434 }
435
read_cstring<R>(mut reader: R) -> io::Result<CString> where R: io::Read,436 fn read_cstring<R>(mut reader: R) -> io::Result<CString>
437 where
438 R: io::Read,
439 {
440 let mut buf = Vec::new();
441 loop {
442 let mut cbuf = [0; 1];
443 reader.read_exact(&mut cbuf)?;
444 if cbuf[0] == 0 {
445 return Ok(unsafe { CString::from_vec_unchecked(buf) });
446 }
447 buf.push(cbuf[0]);
448 }
449 }
450
451 /// Extra field of a GZIP header.
452 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
453 pub struct ExtraField {
454 /// Data of the extra field.
455 pub subfields: Vec<ExtraSubField>,
456 }
457 impl ExtraField {
read_from<R>(mut reader: R) -> io::Result<Self> where R: io::Read,458 fn read_from<R>(mut reader: R) -> io::Result<Self>
459 where
460 R: io::Read,
461 {
462 let mut subfields = Vec::new();
463 let mut buf = [0; 2];
464 reader.read_exact(&mut buf)?;
465 let data_size = u16::from_le_bytes(buf) as usize;
466 let mut reader = reader.take(data_size as u64);
467 while reader.limit() > 0 {
468 subfields.push(ExtraSubField::read_from(&mut reader)?);
469 }
470 Ok(ExtraField { subfields })
471 }
write_to<W>(&self, mut writer: W) -> io::Result<()> where W: io::Write,472 fn write_to<W>(&self, mut writer: W) -> io::Result<()>
473 where
474 W: io::Write,
475 {
476 let len = self.subfields.iter().map(|f| f.write_len()).sum::<usize>();
477 if len > 0xFFFF {
478 return Err(invalid_data_error!("extra field too long: {}", len));
479 }
480 writer.write_all(&(len as u16).to_le_bytes())?;
481 for f in &self.subfields {
482 f.write_to(&mut writer)?;
483 }
484 Ok(())
485 }
486 }
487
488 /// A sub field in the extra field of a GZIP header.
489 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
490 pub struct ExtraSubField {
491 /// ID of the field.
492 pub id: [u8; 2],
493
494 /// Data of the field.
495 pub data: Vec<u8>,
496 }
497 impl ExtraSubField {
read_from<R>(mut reader: R) -> io::Result<Self> where R: io::Read,498 fn read_from<R>(mut reader: R) -> io::Result<Self>
499 where
500 R: io::Read,
501 {
502 let mut field = ExtraSubField {
503 id: [0; 2],
504 data: Vec::new(),
505 };
506
507 reader.read_exact(&mut field.id)?;
508 let mut buf = [0; 2];
509 reader.read_exact(&mut buf)?;
510 let data_size = u16::from_le_bytes(buf) as usize;
511 field.data.resize(data_size, 0);
512 reader.read_exact(&mut field.data)?;
513
514 Ok(field)
515 }
write_to<W>(&self, mut writer: W) -> io::Result<()> where W: io::Write,516 fn write_to<W>(&self, mut writer: W) -> io::Result<()>
517 where
518 W: io::Write,
519 {
520 writer.write_all(&self.id)?;
521 writer.write_all(&(self.data.len() as u16).to_le_bytes())?;
522 writer.write_all(&self.data)?;
523 Ok(())
524 }
write_len(&self) -> usize525 fn write_len(&self) -> usize {
526 4 + self.data.len()
527 }
528 }
529
530 /// OS type.
531 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
532 pub enum Os {
533 /// FAT filesystem (MS-DOS, OS/2, NT/Win32)
534 Fat,
535
536 /// Amiga
537 Amiga,
538
539 /// VMS (or OpenVMS)
540 Vms,
541
542 /// Unix
543 Unix,
544
545 /// VM/CMS
546 VmCms,
547
548 /// Atari TOS
549 AtariTos,
550
551 /// HPFS filesystem (OS/2, NT)
552 Hpfs,
553
554 /// Macintosh
555 Macintosh,
556
557 /// Z-System
558 ZSystem,
559
560 /// CP/M
561 CpM,
562
563 /// TOPS-20
564 Tops20,
565
566 /// NTFS filesystem (NT)
567 Ntfs,
568
569 /// QDOS
570 Qdos,
571
572 /// Acorn RISCOS
573 AcornRiscos,
574
575 /// Unknown
576 Unknown,
577
578 /// Undefined value in RFC-1952
579 Undefined(u8),
580 }
581 impl Os {
to_u8(&self) -> u8582 fn to_u8(&self) -> u8 {
583 match *self {
584 Os::Fat => OS_FAT,
585 Os::Amiga => OS_AMIGA,
586 Os::Vms => OS_VMS,
587 Os::Unix => OS_UNIX,
588 Os::VmCms => OS_VM_CMS,
589 Os::AtariTos => OS_ATARI_TOS,
590 Os::Hpfs => OS_HPFS,
591 Os::Macintosh => OS_MACINTOSH,
592 Os::ZSystem => OS_Z_SYSTEM,
593 Os::CpM => OS_CPM,
594 Os::Tops20 => OS_TOPS20,
595 Os::Ntfs => OS_NTFS,
596 Os::Qdos => OS_QDOS,
597 Os::AcornRiscos => OS_ACORN_RISCOS,
598 Os::Unknown => OS_UNKNOWN,
599 Os::Undefined(os) => os,
600 }
601 }
from_u8(x: u8) -> Self602 fn from_u8(x: u8) -> Self {
603 match x {
604 OS_FAT => Os::Fat,
605 OS_AMIGA => Os::Amiga,
606 OS_VMS => Os::Vms,
607 OS_UNIX => Os::Unix,
608 OS_VM_CMS => Os::VmCms,
609 OS_ATARI_TOS => Os::AtariTos,
610 OS_HPFS => Os::Hpfs,
611 OS_MACINTOSH => Os::Macintosh,
612 OS_Z_SYSTEM => Os::ZSystem,
613 OS_CPM => Os::CpM,
614 OS_TOPS20 => Os::Tops20,
615 OS_NTFS => Os::Ntfs,
616 OS_QDOS => Os::Qdos,
617 OS_ACORN_RISCOS => Os::AcornRiscos,
618 OS_UNKNOWN => Os::Unknown,
619 os => Os::Undefined(os),
620 }
621 }
622 }
623
624 /// Options for a GZIP encoder.
625 #[derive(Debug)]
626 pub struct EncodeOptions<E>
627 where
628 E: lz77::Lz77Encode,
629 {
630 header: Header,
631 options: deflate::EncodeOptions<E>,
632 }
633 impl Default for EncodeOptions<lz77::DefaultLz77Encoder> {
default() -> Self634 fn default() -> Self {
635 EncodeOptions {
636 header: HeaderBuilder::new().finish(),
637 options: Default::default(),
638 }
639 }
640 }
641 impl EncodeOptions<lz77::DefaultLz77Encoder> {
642 /// Makes a default instance.
643 ///
644 /// # Examples
645 /// ```
646 /// use libflate::gzip::{Encoder, EncodeOptions};
647 ///
648 /// let options = EncodeOptions::new();
649 /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
650 /// ```
new() -> Self651 pub fn new() -> Self {
652 Self::default()
653 }
654 }
655 impl<E> EncodeOptions<E>
656 where
657 E: lz77::Lz77Encode,
658 {
659 /// Specifies the LZ77 encoder used to compress input data.
660 ///
661 /// # Example
662 /// ```
663 /// use libflate::lz77::DefaultLz77Encoder;
664 /// use libflate::gzip::{Encoder, EncodeOptions};
665 ///
666 /// let options = EncodeOptions::with_lz77(DefaultLz77Encoder::new());
667 /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
668 /// ```
with_lz77(lz77: E) -> Self669 pub fn with_lz77(lz77: E) -> Self {
670 let mut header = HeaderBuilder::new().finish();
671 header.compression_level = From::from(lz77.compression_level());
672 EncodeOptions {
673 header,
674 options: deflate::EncodeOptions::with_lz77(lz77),
675 }
676 }
677
678 /// Disables LZ77 compression.
679 ///
680 /// # Example
681 /// ```
682 /// use libflate::lz77::DefaultLz77Encoder;
683 /// use libflate::gzip::{Encoder, EncodeOptions};
684 ///
685 /// let options = EncodeOptions::new().no_compression();
686 /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
687 /// ```
no_compression(mut self) -> Self688 pub fn no_compression(mut self) -> Self {
689 self.options = self.options.no_compression();
690 self.header.compression_level = CompressionLevel::Unknown;
691 self
692 }
693
694 /// Sets the GZIP header which will be written to the output stream.
695 ///
696 /// # Example
697 /// ```
698 /// use libflate::gzip::{Encoder, EncodeOptions, HeaderBuilder};
699 ///
700 /// let header = HeaderBuilder::new().text().modification_time(100).finish();
701 /// let options = EncodeOptions::new().header(header);
702 /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
703 /// ```
header(mut self, header: Header) -> Self704 pub fn header(mut self, header: Header) -> Self {
705 self.header = header;
706 self
707 }
708
709 /// Specifies the hint of the size of a DEFLATE block.
710 ///
711 /// The default value is `deflate::DEFAULT_BLOCK_SIZE`.
712 ///
713 /// # Example
714 /// ```
715 /// use libflate::gzip::{Encoder, EncodeOptions};
716 ///
717 /// let options = EncodeOptions::new().block_size(512 * 1024);
718 /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
719 /// ```
block_size(mut self, size: usize) -> Self720 pub fn block_size(mut self, size: usize) -> Self {
721 self.options = self.options.block_size(size);
722 self
723 }
724
725 /// Specifies to compress with fixed huffman codes.
726 ///
727 /// # Example
728 /// ```
729 /// use libflate::gzip::{Encoder, EncodeOptions};
730 ///
731 /// let options = EncodeOptions::new().fixed_huffman_codes();
732 /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
733 /// ```
fixed_huffman_codes(mut self) -> Self734 pub fn fixed_huffman_codes(mut self) -> Self {
735 self.options = self.options.fixed_huffman_codes();
736 self
737 }
738 }
739
740 /// GZIP encoder.
741 pub struct Encoder<W, E = lz77::DefaultLz77Encoder> {
742 header: Header,
743 crc32: checksum::Crc32,
744 input_size: u32,
745 writer: deflate::Encoder<W, E>,
746 }
747 impl<W> Encoder<W, lz77::DefaultLz77Encoder>
748 where
749 W: io::Write,
750 {
751 /// Makes a new encoder instance.
752 ///
753 /// Encoded GZIP stream is written to `inner`.
754 ///
755 /// # Examples
756 /// ```
757 /// use std::io::Write;
758 /// use libflate::gzip::Encoder;
759 ///
760 /// let mut encoder = Encoder::new(Vec::new()).unwrap();
761 /// encoder.write_all(b"Hello World!").unwrap();
762 /// encoder.finish().into_result().unwrap();
763 /// ```
new(inner: W) -> io::Result<Self>764 pub fn new(inner: W) -> io::Result<Self> {
765 Self::with_options(inner, EncodeOptions::new())
766 }
767 }
768 impl<W, E> Encoder<W, E>
769 where
770 W: io::Write,
771 E: lz77::Lz77Encode,
772 {
773 /// Makes a new encoder instance with specified options.
774 ///
775 /// Encoded GZIP stream is written to `inner`.
776 ///
777 /// # Examples
778 /// ```
779 /// use std::io::Write;
780 /// use libflate::gzip::{Encoder, EncodeOptions, HeaderBuilder};
781 ///
782 /// let header = HeaderBuilder::new().modification_time(123).finish();
783 /// let options = EncodeOptions::new().no_compression().header(header);
784 /// let mut encoder = Encoder::with_options(Vec::new(), options).unwrap();
785 /// encoder.write_all(b"Hello World!").unwrap();
786 ///
787 /// assert_eq!(encoder.finish().into_result().unwrap(),
788 /// &[31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255, 72, 101, 108, 108,
789 /// 111, 32, 87, 111, 114, 108, 100, 33, 163, 28, 41, 28, 12, 0, 0, 0][..]);
790 /// ```
with_options(mut inner: W, options: EncodeOptions<E>) -> io::Result<Self>791 pub fn with_options(mut inner: W, options: EncodeOptions<E>) -> io::Result<Self> {
792 options.header.write_to(&mut inner)?;
793 Ok(Encoder {
794 header: options.header.clone(),
795 crc32: checksum::Crc32::new(),
796 input_size: 0,
797 writer: deflate::Encoder::with_options(inner, options.options),
798 })
799 }
800
801 /// Returns the header of the GZIP stream.
802 ///
803 /// # Examples
804 /// ```
805 /// use libflate::gzip::{Encoder, Os};
806 ///
807 /// let encoder = Encoder::new(Vec::new()).unwrap();
808 /// assert_eq!(encoder.header().os(), Os::Unix);
809 /// ```
header(&self) -> &Header810 pub fn header(&self) -> &Header {
811 &self.header
812 }
813
814 /// Writes the GZIP trailer and returns the inner stream.
815 ///
816 /// # Examples
817 /// ```
818 /// use std::io::Write;
819 /// use libflate::gzip::Encoder;
820 ///
821 /// let mut encoder = Encoder::new(Vec::new()).unwrap();
822 /// encoder.write_all(b"Hello World!").unwrap();
823 ///
824 /// assert!(encoder.finish().as_result().is_ok())
825 /// ```
826 ///
827 /// # Note
828 ///
829 /// If you are not concerned the result of this encoding,
830 /// it may be convenient to use `AutoFinishUnchecked` instead of the explicit invocation of this method.
831 ///
832 /// ```
833 /// use std::io;
834 /// use libflate::finish::AutoFinishUnchecked;
835 /// use libflate::gzip::Encoder;
836 ///
837 /// let plain = b"Hello World!";
838 /// let mut buf = Vec::new();
839 /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap());
840 /// io::copy(&mut &plain[..], &mut encoder).unwrap();
841 /// ```
finish(self) -> Finish<W, io::Error>842 pub fn finish(self) -> Finish<W, io::Error> {
843 let trailer = Trailer {
844 crc32: self.crc32.value(),
845 input_size: self.input_size,
846 };
847 let mut inner = finish_try!(self.writer.finish());
848 match trailer.write_to(&mut inner).and_then(|_| inner.flush()) {
849 Ok(_) => Finish::new(inner, None),
850 Err(e) => Finish::new(inner, Some(e)),
851 }
852 }
853
854 /// Returns the immutable reference to the inner stream.
as_inner_ref(&self) -> &W855 pub fn as_inner_ref(&self) -> &W {
856 self.writer.as_inner_ref()
857 }
858
859 /// Returns the mutable reference to the inner stream.
as_inner_mut(&mut self) -> &mut W860 pub fn as_inner_mut(&mut self) -> &mut W {
861 self.writer.as_inner_mut()
862 }
863
864 /// Unwraps the `Encoder`, returning the inner stream.
into_inner(self) -> W865 pub fn into_inner(self) -> W {
866 self.writer.into_inner()
867 }
868 }
869 impl<W, E> io::Write for Encoder<W, E>
870 where
871 W: io::Write,
872 E: lz77::Lz77Encode,
873 {
write(&mut self, buf: &[u8]) -> io::Result<usize>874 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
875 let written_size = self.writer.write(buf)?;
876 self.crc32.update(&buf[..written_size]);
877 self.input_size = self.input_size.wrapping_add(written_size as u32);
878 Ok(written_size)
879 }
flush(&mut self) -> io::Result<()>880 fn flush(&mut self) -> io::Result<()> {
881 self.writer.flush()
882 }
883 }
884 impl<W, E> Complete for Encoder<W, E>
885 where
886 W: io::Write,
887 E: lz77::Lz77Encode,
888 {
complete(self) -> io::Result<()>889 fn complete(self) -> io::Result<()> {
890 self.finish().into_result().map(|_| ())
891 }
892 }
893
894 /// GZIP decoder.
895 #[derive(Debug)]
896 pub struct Decoder<R> {
897 header: Header,
898 reader: deflate::Decoder<R>,
899 crc32: checksum::Crc32,
900 eos: bool,
901 }
902 impl<R> Decoder<R>
903 where
904 R: io::Read,
905 {
906 /// Makes a new decoder instance.
907 ///
908 /// `inner` is to be decoded GZIP stream.
909 ///
910 /// # Examples
911 /// ```
912 /// use std::io::Read;
913 /// use libflate::gzip::Decoder;
914 ///
915 /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
916 /// 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
917 /// 163, 28, 41, 28, 12, 0, 0, 0];
918 ///
919 /// let mut decoder = Decoder::new(&encoded_data[..]).unwrap();
920 /// let mut buf = Vec::new();
921 /// decoder.read_to_end(&mut buf).unwrap();
922 ///
923 /// assert_eq!(buf, b"Hello World!");
924 /// ```
new(mut inner: R) -> io::Result<Self>925 pub fn new(mut inner: R) -> io::Result<Self> {
926 let header = Header::read_from(&mut inner)?;
927 Ok(Self::with_header(inner, header))
928 }
929
930 /// Returns the header of the GZIP stream.
931 ///
932 /// # Examples
933 /// ```
934 /// use libflate::gzip::{Decoder, Os};
935 ///
936 /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
937 /// 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
938 /// 163, 28, 41, 28, 12, 0, 0, 0];
939 ///
940 /// let decoder = Decoder::new(&encoded_data[..]).unwrap();
941 /// assert_eq!(decoder.header().os(), Os::Unix);
942 /// ```
header(&self) -> &Header943 pub fn header(&self) -> &Header {
944 &self.header
945 }
946
947 /// Returns the immutable reference to the inner stream.
as_inner_ref(&self) -> &R948 pub fn as_inner_ref(&self) -> &R {
949 self.reader.as_inner_ref()
950 }
951
952 /// Returns the mutable reference to the inner stream.
as_inner_mut(&mut self) -> &mut R953 pub fn as_inner_mut(&mut self) -> &mut R {
954 self.reader.as_inner_mut()
955 }
956
957 /// Unwraps this `Decoder`, returning the underlying reader.
958 ///
959 /// # Examples
960 /// ```
961 /// use std::io::Cursor;
962 /// use libflate::gzip::Decoder;
963 ///
964 /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
965 /// 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
966 /// 163, 28, 41, 28, 12, 0, 0, 0];
967 ///
968 /// let decoder = Decoder::new(Cursor::new(&encoded_data[..])).unwrap();
969 /// assert_eq!(decoder.into_inner().into_inner(), &encoded_data[..]);
970 /// ```
into_inner(self) -> R971 pub fn into_inner(self) -> R {
972 self.reader.into_inner()
973 }
974
with_header(inner: R, header: Header) -> Self975 fn with_header(inner: R, header: Header) -> Self {
976 Decoder {
977 header,
978 reader: deflate::Decoder::new(inner),
979 crc32: checksum::Crc32::new(),
980 eos: false,
981 }
982 }
983
reset(&mut self, header: Header)984 fn reset(&mut self, header: Header) {
985 self.header = header;
986 self.reader.reset();
987 self.crc32 = checksum::Crc32::new();
988 self.eos = false;
989 }
990 }
991 impl<R> io::Read for Decoder<R>
992 where
993 R: io::Read,
994 {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>995 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
996 if self.eos {
997 Ok(0)
998 } else {
999 let read_size = self.reader.read(buf)?;
1000 self.crc32.update(&buf[..read_size]);
1001 if read_size == 0 {
1002 if buf.is_empty() {
1003 return Ok(0);
1004 }
1005
1006 self.eos = true;
1007 let trailer = Trailer::read_from(self.reader.as_inner_mut())?;
1008 // checksum verification is skipped during fuzzing
1009 // so that random data from fuzzer can reach actually interesting code
1010 // Compilation flag 'fuzzing' is automatically set by all 3 Rust fuzzers.
1011 if cfg!(not(fuzzing)) && trailer.crc32 != self.crc32.value() {
1012 Err(invalid_data_error!(
1013 "CRC32 mismatched: value={}, expected={}",
1014 self.crc32.value(),
1015 trailer.crc32
1016 ))
1017 } else {
1018 Ok(0)
1019 }
1020 } else {
1021 Ok(read_size)
1022 }
1023 }
1024 }
1025 }
1026
1027 /// A decoder that decodes all members in a GZIP stream.
1028 #[derive(Debug)]
1029 pub struct MultiDecoder<R> {
1030 decoder: Decoder<R>,
1031 eos: bool,
1032 }
1033 impl<R> MultiDecoder<R>
1034 where
1035 R: io::Read,
1036 {
1037 /// Makes a new decoder instance.
1038 ///
1039 /// `inner` is to be decoded GZIP stream.
1040 ///
1041 /// # Examples
1042 /// ```
1043 /// use std::io::Read;
1044 /// use libflate::gzip::MultiDecoder;
1045 ///
1046 /// let mut encoded_data = Vec::new();
1047 ///
1048 /// // Add a member (a GZIP binary that represents "Hello ")
1049 /// encoded_data.extend(&[31, 139, 8, 0, 51, 206, 75, 90, 0, 3, 5, 128, 49, 9, 0, 0, 0, 194, 170, 24,
1050 /// 199, 34, 126, 3, 251, 127, 163, 131, 71, 192, 252, 45, 234, 6, 0, 0, 0][..]);
1051 ///
1052 /// // Add another member (a GZIP binary that represents "World!")
1053 /// encoded_data.extend(&[31, 139, 8, 0, 227, 207, 75, 90, 0, 3, 5, 128, 49, 9, 0, 0, 0, 194, 178, 152,
1054 /// 202, 2, 158, 130, 96, 255, 99, 120, 111, 4, 222, 157, 40, 118, 6, 0, 0, 0][..]);
1055 ///
1056 /// let mut decoder = MultiDecoder::new(&encoded_data[..]).unwrap();
1057 /// let mut buf = Vec::new();
1058 /// decoder.read_to_end(&mut buf).unwrap();
1059 ///
1060 /// assert_eq!(buf, b"Hello World!");
1061 /// ```
new(inner: R) -> io::Result<Self>1062 pub fn new(inner: R) -> io::Result<Self> {
1063 let decoder = Decoder::new(inner)?;
1064 Ok(MultiDecoder {
1065 decoder,
1066 eos: false,
1067 })
1068 }
1069
1070 /// Returns the header of the current member in the GZIP stream.
1071 ///
1072 /// # Examples
1073 /// ```
1074 /// use libflate::gzip::{MultiDecoder, Os};
1075 ///
1076 /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
1077 /// 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
1078 /// 163, 28, 41, 28, 12, 0, 0, 0];
1079 ///
1080 /// let decoder = MultiDecoder::new(&encoded_data[..]).unwrap();
1081 /// assert_eq!(decoder.header().os(), Os::Unix);
1082 /// ```
header(&self) -> &Header1083 pub fn header(&self) -> &Header {
1084 self.decoder.header()
1085 }
1086
1087 /// Returns the immutable reference to the inner stream.
as_inner_ref(&self) -> &R1088 pub fn as_inner_ref(&self) -> &R {
1089 self.decoder.as_inner_ref()
1090 }
1091
1092 /// Returns the mutable reference to the inner stream.
as_inner_mut(&mut self) -> &mut R1093 pub fn as_inner_mut(&mut self) -> &mut R {
1094 self.decoder.as_inner_mut()
1095 }
1096
1097 /// Unwraps this `MultiDecoder`, returning the underlying reader.
1098 ///
1099 /// # Examples
1100 /// ```
1101 /// use std::io::Cursor;
1102 /// use libflate::gzip::MultiDecoder;
1103 ///
1104 /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
1105 /// 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
1106 /// 163, 28, 41, 28, 12, 0, 0, 0];
1107 ///
1108 /// let decoder = MultiDecoder::new(Cursor::new(&encoded_data[..])).unwrap();
1109 /// assert_eq!(decoder.into_inner().into_inner(), &encoded_data[..]);
1110 /// ```
into_inner(self) -> R1111 pub fn into_inner(self) -> R {
1112 self.decoder.into_inner()
1113 }
1114 }
1115 impl<R> io::Read for MultiDecoder<R>
1116 where
1117 R: io::Read,
1118 {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>1119 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1120 if self.eos {
1121 return Ok(0);
1122 }
1123
1124 let read_size = self.decoder.read(buf)?;
1125 if read_size == 0 {
1126 match Header::read_from(self.as_inner_mut()) {
1127 Err(e) => {
1128 if e.kind() == io::ErrorKind::UnexpectedEof {
1129 self.eos = true;
1130 Ok(0)
1131 } else {
1132 Err(e)
1133 }
1134 }
1135 Ok(header) => {
1136 self.decoder.reset(header);
1137 self.read(buf)
1138 }
1139 }
1140 } else {
1141 Ok(read_size)
1142 }
1143 }
1144 }
1145
1146 #[cfg(test)]
1147 mod tests {
1148 use super::*;
1149 use crate::finish::AutoFinish;
1150 use std::io::{self, Read, Write};
1151
decode(buf: &[u8]) -> io::Result<Vec<u8>>1152 fn decode(buf: &[u8]) -> io::Result<Vec<u8>> {
1153 let mut decoder = Decoder::new(buf).unwrap();
1154 let mut buf = Vec::with_capacity(buf.len());
1155 io::copy(&mut decoder, &mut buf)?;
1156 Ok(buf)
1157 }
1158
decode_multi(buf: &[u8]) -> io::Result<Vec<u8>>1159 fn decode_multi(buf: &[u8]) -> io::Result<Vec<u8>> {
1160 let mut decoder = MultiDecoder::new(buf).unwrap();
1161 let mut buf = Vec::with_capacity(buf.len());
1162 io::copy(&mut decoder, &mut buf)?;
1163 Ok(buf)
1164 }
1165
encode(text: &[u8]) -> io::Result<Vec<u8>>1166 fn encode(text: &[u8]) -> io::Result<Vec<u8>> {
1167 let mut encoder = Encoder::new(Vec::new()).unwrap();
1168 io::copy(&mut &text[..], &mut encoder).unwrap();
1169 encoder.finish().into_result()
1170 }
1171
1172 #[test]
encode_works()1173 fn encode_works() {
1174 let plain = b"Hello World! Hello GZIP!!";
1175 let mut encoder = Encoder::new(Vec::new()).unwrap();
1176 io::copy(&mut &plain[..], &mut encoder).unwrap();
1177 let encoded = encoder.finish().into_result().unwrap();
1178 assert_eq!(decode(&encoded).unwrap(), plain);
1179 }
1180
1181 #[test]
encoder_auto_finish_works()1182 fn encoder_auto_finish_works() {
1183 let plain = b"Hello World! Hello GZIP!!";
1184 let mut buf = Vec::new();
1185 {
1186 let mut encoder = AutoFinish::new(Encoder::new(&mut buf).unwrap());
1187 io::copy(&mut &plain[..], &mut encoder).unwrap();
1188 }
1189 assert_eq!(decode(&buf).unwrap(), plain);
1190 }
1191
1192 #[test]
multi_decode_works()1193 fn multi_decode_works() {
1194 use std::iter;
1195 let text = b"Hello World!";
1196 let encoded: Vec<u8> = iter::repeat(encode(text).unwrap())
1197 .take(2)
1198 .flat_map(|b| b)
1199 .collect();
1200 assert_eq!(decode(&encoded).unwrap(), b"Hello World!");
1201 assert_eq!(decode_multi(&encoded).unwrap(), b"Hello World!Hello World!");
1202 }
1203
1204 #[test]
1205 /// See: https://github.com/sile/libflate/issues/15 and https://github.com/RazrFalcon/usvg/issues/20
issue_15_1()1206 fn issue_15_1() {
1207 let data = b"\x1F\x8B\x08\xC1\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x7B\x80\x80\x80\x80\x7B\x7B\x7B\x7B\x7B\x7B\x97\x7B\x7B\x7B\x86\x27\xEB\x60\xA7\xA8\x46\x6E\x1F\x33\x51\x5C\x34\xE0\xD2\x2E\xE8\x0C\x19\x1D\x3D\x3C\xFD\x3B\x6A\xFA\x63\xDF\x28\x87\x86\xF2\xA6\xAC\x87\x86\xF2\xA6\xAC\xD5";
1208 assert!(decode(&data[..]).is_err());
1209 }
1210
1211 #[test]
1212 /// See: https://github.com/sile/libflate/issues/15 and https://github.com/RazrFalcon/usvg/issues/21
issue_15_2()1213 fn issue_15_2() {
1214 let data = b"\x1F\x8B\x08\xC1\x7B\x7B\x7B\x7B\x7B\xFC\x5D\x2D\xDC\x08\xC1\x7B\x7B\x7B\x7B\x7B\xFC\x5D\x2D\xDC\x08\xC1\x7B\x7F\x7B\x7B\x7B\xFC\x5D\x2D\xDC\x69\x32\x48\x22\x5A\x81\x81\x42\x42\x81\x7E\x81\x81\x81\x81\xF2\x17";
1215 assert!(decode(&data[..]).is_err());
1216 }
1217
1218 #[test]
1219 /// See: https://github.com/sile/libflate/issues/15 and https://github.com/RazrFalcon/usvg/issues/22
issue_15_3()1220 fn issue_15_3() {
1221 let data = b"\x1F\x8B\x08\xC1\x91\x28\x71\xDC\xF2\x2D\x34\x35\x31\x35\x34\x30\x70\x6E\x60\x35\x31\x32\x32\x33\x32\x33\x37\x32\x36\x38\xDD\x1C\xE5\x2A\xDD\xDD\xDD\x22\xDD\xDD\xDD\xDC\x88\x13\xC9\x40\x60\xA7";
1222 assert!(decode(&data[..]).is_err());
1223 }
1224
1225 #[test]
1226 /// See: https://github.com/sile/libflate/issues/61
issue_61()1227 fn issue_61() {
1228 let data = encode(b"Hello World").unwrap();
1229 let mut decoder = Decoder::new(&data[..]).unwrap();
1230 let mut buf = Vec::new();
1231 decoder.read(&mut buf).unwrap();
1232 io::copy(&mut decoder, &mut buf).unwrap();
1233 assert_eq!(buf, b"Hello World");
1234 }
1235
1236 #[test]
extra_field()1237 fn extra_field() {
1238 let f = ExtraField {
1239 subfields: vec![ExtraSubField {
1240 id: [0, 0x42],
1241 data: "abc".into(),
1242 }],
1243 };
1244
1245 let mut buf = Vec::new();
1246 f.write_to(&mut buf).unwrap();
1247
1248 assert_eq!(ExtraField::read_from(&buf[..]).unwrap(), f);
1249 }
1250
1251 #[test]
encode_with_extra_field()1252 fn encode_with_extra_field() {
1253 let mut buf = Vec::new();
1254 let extra_field = ExtraField {
1255 subfields: vec![ExtraSubField {
1256 id: [0, 0x42],
1257 data: "abc".into(),
1258 }],
1259 };
1260 {
1261 // encode
1262 let header = HeaderBuilder::new()
1263 .extra_field(extra_field.clone())
1264 .finish();
1265
1266 let ops = EncodeOptions::new().header(header);
1267 let mut encoder = Encoder::with_options(&mut buf, ops).unwrap();
1268 write!(encoder, "hello world").unwrap();
1269 encoder.finish().as_result().unwrap();
1270 }
1271 {
1272 // decode
1273 let mut decoder = Decoder::new(&buf[..]).unwrap();
1274 io::copy(&mut decoder, &mut io::sink()).unwrap();
1275 assert_eq!(decoder.header().extra_field(), Some(&extra_field));
1276 }
1277 }
1278 }
1279