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