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