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