Skip to main content

libflate/
zlib.rs

1//! The encoder and decoder of the ZLIB format.
2//!
3//! The ZLIB format is defined in [RFC-1950](https://tools.ietf.org/html/rfc1950).
4//!
5//! # Examples
6//! ```
7//! use no_std_io2::io::{Read, Write};
8//! use libflate::zlib::{Encoder, Decoder};
9//!
10//! // Encoding
11//! let mut encoder = Encoder::new(Vec::new()).unwrap();
12//! encoder.write_all(&b"Hello World!"[..]).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//! ```
22use crate::checksum;
23use crate::deflate;
24use crate::finish::{Complete, Finish};
25use crate::lz77;
26use no_std_io2::io;
27
28const COMPRESSION_METHOD_DEFLATE: u8 = 8;
29
30/// Compression levels defined by the ZLIB format.
31#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
32pub enum CompressionLevel {
33    /// Compressor used fastest algorithm.
34    Fastest = 0,
35
36    /// Compressor used fast algorithm.
37    Fast = 1,
38
39    /// Compressor used default algorithm.
40    Default = 2,
41
42    /// Compressor used maximum compression, slowest algorithm.
43    Slowest = 3,
44}
45impl CompressionLevel {
46    fn from_u2(level: u8) -> Self {
47        match level {
48            0 => CompressionLevel::Fastest,
49            1 => CompressionLevel::Fast,
50            2 => CompressionLevel::Default,
51            3 => CompressionLevel::Slowest,
52            _ => unreachable!(),
53        }
54    }
55    fn as_u2(&self) -> u8 {
56        self.clone() as u8
57    }
58}
59impl From<lz77::CompressionLevel> for CompressionLevel {
60    fn from(f: lz77::CompressionLevel) -> Self {
61        match f {
62            lz77::CompressionLevel::None => CompressionLevel::Fastest,
63            lz77::CompressionLevel::Fast => CompressionLevel::Fast,
64            lz77::CompressionLevel::Balance => CompressionLevel::Default,
65            lz77::CompressionLevel::Best => CompressionLevel::Slowest,
66        }
67    }
68}
69
70/// LZ77 Window sizes defined by the ZLIB format.
71#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
72// TODO: Use `#[allow(clippy::upper_case_acronyms)]` instead once it gets available on the stable branch
73#[allow(clippy::all)]
74pub enum Lz77WindowSize {
75    /// 256 bytes
76    B256 = 0,
77
78    /// 512 btyes
79    B512 = 1,
80
81    /// 1 kilobyte
82    KB1 = 2,
83
84    /// 2 kilobytes
85    KB2 = 3,
86
87    /// 4 kitobytes
88    KB4 = 4,
89
90    /// 8 kitobytes
91    KB8 = 5,
92
93    /// 16 kitobytes
94    KB16 = 6,
95
96    /// 32 kitobytes
97    KB32 = 7,
98}
99impl Lz77WindowSize {
100    fn from_u4(compression_info: u8) -> Option<Self> {
101        match compression_info {
102            0 => Some(Lz77WindowSize::B256),
103            1 => Some(Lz77WindowSize::B512),
104            2 => Some(Lz77WindowSize::KB1),
105            3 => Some(Lz77WindowSize::KB2),
106            4 => Some(Lz77WindowSize::KB4),
107            5 => Some(Lz77WindowSize::KB8),
108            6 => Some(Lz77WindowSize::KB16),
109            7 => Some(Lz77WindowSize::KB32),
110            _ => None,
111        }
112    }
113    fn as_u4(&self) -> u8 {
114        self.clone() as u8
115    }
116
117    /// Converts from `u16` to Lz77WindowSize`.
118    ///
119    /// Fractions are rounded to next upper window size.
120    /// If `size` exceeds maximum window size,
121    /// `lz77::MAX_WINDOW_SIZE` will be used instead.
122    ///
123    /// # Examples
124    /// ```
125    /// use libflate::zlib::Lz77WindowSize;
126    ///
127    /// assert_eq!(Lz77WindowSize::from_u16(15000), Lz77WindowSize::KB16);
128    /// assert_eq!(Lz77WindowSize::from_u16(16384), Lz77WindowSize::KB16);
129    /// assert_eq!(Lz77WindowSize::from_u16(16385), Lz77WindowSize::KB32);
130    /// assert_eq!(Lz77WindowSize::from_u16(40000), Lz77WindowSize::KB32);
131    /// ```
132    pub fn from_u16(size: u16) -> Self {
133        use self::Lz77WindowSize::*;
134        if 16_384 < size {
135            KB32
136        } else if 8192 < size {
137            KB16
138        } else if 4096 < size {
139            KB8
140        } else if 2048 < size {
141            KB4
142        } else if 1024 < size {
143            KB2
144        } else if 512 < size {
145            KB1
146        } else if 256 < size {
147            B512
148        } else {
149            B256
150        }
151    }
152
153    /// Converts from `Lz77WindowSize` to `u16`.
154    ///
155    /// # Examples
156    /// ```
157    /// use libflate::zlib::Lz77WindowSize;
158    ///
159    /// assert_eq!(Lz77WindowSize::KB16.to_u16(), 16384u16);
160    /// ```
161    pub fn to_u16(&self) -> u16 {
162        use self::Lz77WindowSize::*;
163        match *self {
164            B256 => 256,
165            B512 => 512,
166            KB1 => 1024,
167            KB2 => 2048,
168            KB4 => 4096,
169            KB8 => 8192,
170            KB16 => 16_384,
171            KB32 => 32_768,
172        }
173    }
174}
175
176/// [zlib] library specific parameter for defining behavior when `Write::flush` method is called.
177///
178/// # References
179///
180/// - [Zlib Manual](https://www.zlib.net/manual.html)
181/// - [Zlib Flush Modes](https://www.bolet.org/~pornin/deflate-flush.html)
182///
183/// [zlib]: https://www.zlib.net/
184#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
185pub enum FlushMode {
186    /// `Z_NO_FLUSH` (default).
187    ///
188    /// Note that when this parameter is specified,
189    /// no `zlib` specific processing will not be executed but ordinal DEFLATE layer flushing will be performed.
190    #[default]
191    None = 0,
192
193    /// `Z_SYNC_FLUSH`.
194    Sync = 2,
195}
196
197/// ZLIB header.
198#[derive(Debug, Clone, PartialEq, Eq, Hash)]
199pub struct Header {
200    window_size: Lz77WindowSize,
201    compression_level: CompressionLevel,
202}
203impl Header {
204    /// Returns the LZ77 window size stored in the header.
205    pub fn window_size(&self) -> Lz77WindowSize {
206        self.window_size.clone()
207    }
208    /// Returns the compression level stored in the header.
209    pub fn compression_level(&self) -> CompressionLevel {
210        self.compression_level.clone()
211    }
212    fn from_lz77<E>(lz77: &E) -> Self
213    where
214        E: lz77::Lz77Encode,
215    {
216        Header {
217            compression_level: From::from(lz77.compression_level()),
218            window_size: Lz77WindowSize::from_u16(lz77.window_size()),
219        }
220    }
221    pub(crate) fn read_from<R>(mut reader: R) -> io::Result<Self>
222    where
223        R: io::Read,
224    {
225        let mut buf = [0; 2];
226        reader.read_exact(&mut buf)?;
227        let [cmf, flg] = buf;
228        let check = (u16::from(cmf) << 8) + u16::from(flg);
229        if check % 31 != 0 {
230            return Err(invalid_data_error!(
231                "Inconsistent ZLIB check bits: `CMF({}) * 256 + \
232                 FLG({})` must be a multiple of 31",
233                cmf,
234                flg
235            ));
236        }
237
238        let compression_method = cmf & 0b1111;
239        let compression_info = cmf >> 4;
240        if compression_method != COMPRESSION_METHOD_DEFLATE {
241            return Err(invalid_data_error!(
242                "Compression methods other than DEFLATE(8) are \
243                 unsupported: method={}",
244                compression_method
245            ));
246        }
247        let window_size = Lz77WindowSize::from_u4(compression_info).ok_or_else(|| {
248            invalid_data_error!("CINFO above 7 are not allowed: value={}", compression_info)
249        })?;
250
251        let dict_flag = (flg & 0b10_0000) != 0;
252        if dict_flag {
253            let mut buf = [0; 4];
254            reader.read_exact(&mut buf)?;
255            return Err(invalid_data_error!(
256                "Preset dictionaries are not supported: \
257                 dictionary_id=0x{:X}",
258                u32::from_be_bytes(buf)
259            ));
260        }
261        let compression_level = CompressionLevel::from_u2(flg >> 6);
262        Ok(Header {
263            window_size,
264            compression_level,
265        })
266    }
267    fn write_to<W>(&self, mut writer: W) -> io::Result<()>
268    where
269        W: io::Write,
270    {
271        let cmf = (self.window_size.as_u4() << 4) | COMPRESSION_METHOD_DEFLATE;
272        let mut flg = self.compression_level.as_u2() << 6;
273        let check = (u16::from(cmf) << 8) + u16::from(flg);
274        if check % 31 != 0 {
275            flg += (31 - check % 31) as u8;
276        }
277        writer.write_all(&[cmf, flg])?;
278        Ok(())
279    }
280}
281
282/// ZLIB decoder.
283#[derive(Debug)]
284pub struct Decoder<R> {
285    header: Header,
286    reader: deflate::Decoder<R>,
287    adler32: checksum::Adler32,
288    eos: bool,
289}
290impl<R> Decoder<R>
291where
292    R: io::Read,
293{
294    /// Makes a new decoder instance.
295    ///
296    /// `inner` is to be decoded ZLIB stream.
297    ///
298    /// # Examples
299    /// ```
300    /// use no_std_io2::io::Read;
301    /// use libflate::zlib::Decoder;
302    ///
303    /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47,
304    ///                     202, 73, 81, 4, 0, 28, 73, 4, 62];
305    ///
306    /// let mut decoder = Decoder::new(&encoded_data[..]).unwrap();
307    /// let mut buf = Vec::new();
308    /// decoder.read_to_end(&mut buf).unwrap();
309    ///
310    /// assert_eq!(buf, b"Hello World!");
311    /// ```
312    pub fn new(mut inner: R) -> io::Result<Self> {
313        let header = Header::read_from(&mut inner)?;
314        Ok(Decoder {
315            header,
316            reader: deflate::Decoder::new(inner),
317            adler32: checksum::Adler32::new(),
318            eos: false,
319        })
320    }
321
322    /// Returns the header of the ZLIB stream.
323    ///
324    /// # Examples
325    /// ```
326    /// use libflate::zlib::{Decoder, CompressionLevel};
327    ///
328    /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47,
329    ///                     202, 73, 81, 4, 0, 28, 73, 4, 62];
330    ///
331    /// let decoder = Decoder::new(&encoded_data[..]).unwrap();
332    /// assert_eq!(decoder.header().compression_level(),
333    ///            CompressionLevel::Default);
334    /// ```
335    pub fn header(&self) -> &Header {
336        &self.header
337    }
338
339    /// Returns the immutable reference to the inner stream.
340    pub fn as_inner_ref(&self) -> &R {
341        self.reader.as_inner_ref()
342    }
343
344    /// Returns the mutable reference to the inner stream.
345    pub fn as_inner_mut(&mut self) -> &mut R {
346        self.reader.as_inner_mut()
347    }
348
349    /// Unwraps this `Decoder`, returning the underlying reader.
350    ///
351    /// # Examples
352    /// ```
353    /// use no_std_io2::io::Cursor;
354    /// use libflate::zlib::Decoder;
355    ///
356    /// let encoded_data = [120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47,
357    ///                     202, 73, 81, 4, 0, 28, 73, 4, 62];
358    ///
359    /// let decoder = Decoder::new(Cursor::new(&encoded_data)).unwrap();
360    /// assert_eq!(decoder.into_inner().into_inner(), &encoded_data);
361    /// ```
362    pub fn into_inner(self) -> R {
363        self.reader.into_inner()
364    }
365
366    /// Returns the data that has been decoded but has not yet been read.
367    ///
368    /// This method is useful to retrieve partial decoded data when the decoding process is failed.
369    pub fn unread_decoded_data(&self) -> &[u8] {
370        self.reader.unread_decoded_data()
371    }
372}
373impl<R> io::Read for Decoder<R>
374where
375    R: io::Read,
376{
377    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
378        if self.eos {
379            Ok(0)
380        } else {
381            let read_size = self.reader.read(buf)?;
382            if read_size == 0 {
383                if buf.is_empty() {
384                    return Ok(0);
385                }
386
387                self.eos = true;
388                let mut buf = [0; 4];
389                self.reader.as_inner_mut().read_exact(&mut buf)?;
390                let adler32 = u32::from_be_bytes(buf);
391
392                // checksum verification is skipped during fuzzing
393                // so that random data from fuzzer can reach actually interesting code
394                // Compilation flag 'fuzzing' is automatically set by all 3 Rust fuzzers.
395                if cfg!(not(fuzzing)) && adler32 != self.adler32.value() {
396                    Err(invalid_data_error!(
397                        "Adler32 checksum mismatched: value={}, expected={}",
398                        self.adler32.value(),
399                        adler32
400                    ))
401                } else {
402                    Ok(0)
403                }
404            } else {
405                self.adler32.update(&buf[..read_size]);
406                Ok(read_size)
407            }
408        }
409    }
410}
411
412/// Options for a ZLIB encoder.
413#[derive(Debug)]
414pub struct EncodeOptions<E>
415where
416    E: lz77::Lz77Encode,
417{
418    header: Header,
419    options: deflate::EncodeOptions<E>,
420    flush_mode: FlushMode,
421}
422impl Default for EncodeOptions<lz77::DefaultLz77Encoder> {
423    fn default() -> Self {
424        EncodeOptions {
425            header: Header::from_lz77(&lz77::DefaultLz77Encoder::new()),
426            options: Default::default(),
427            flush_mode: FlushMode::None,
428        }
429    }
430}
431impl EncodeOptions<lz77::DefaultLz77Encoder> {
432    /// Makes a default instance.
433    ///
434    /// # Examples
435    /// ```
436    /// use libflate::zlib::{Encoder, EncodeOptions};
437    ///
438    /// let options = EncodeOptions::new();
439    /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
440    /// ```
441    pub fn new() -> Self {
442        Self::default()
443    }
444}
445impl<E> EncodeOptions<E>
446where
447    E: lz77::Lz77Encode,
448{
449    /// Specifies the LZ77 encoder used to compress input data.
450    ///
451    /// # Example
452    /// ```
453    /// use libflate::lz77::DefaultLz77Encoder;
454    /// use libflate::zlib::{Encoder, EncodeOptions};
455    ///
456    /// let options = EncodeOptions::with_lz77(DefaultLz77Encoder::new());
457    /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
458    /// ```
459    pub fn with_lz77(lz77: E) -> Self {
460        EncodeOptions {
461            header: Header::from_lz77(&lz77),
462            options: deflate::EncodeOptions::with_lz77(lz77),
463            flush_mode: FlushMode::None,
464        }
465    }
466
467    /// Disables LZ77 compression.
468    ///
469    /// # Example
470    /// ```
471    /// use libflate::lz77::DefaultLz77Encoder;
472    /// use libflate::zlib::{Encoder, EncodeOptions};
473    ///
474    /// let options = EncodeOptions::new().no_compression();
475    /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
476    /// ```
477    pub fn no_compression(mut self) -> Self {
478        self.options = self.options.no_compression();
479        self.header.compression_level = CompressionLevel::Fastest;
480        self
481    }
482
483    /// Specifies the hint of the size of a DEFLATE block.
484    ///
485    /// The default value is `deflate::DEFAULT_BLOCK_SIZE`.
486    ///
487    /// # Example
488    /// ```
489    /// use libflate::zlib::{Encoder, EncodeOptions};
490    ///
491    /// let options = EncodeOptions::new().block_size(512 * 1024);
492    /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
493    /// ```
494    pub fn block_size(mut self, size: usize) -> Self {
495        self.options = self.options.block_size(size);
496        self
497    }
498
499    /// Specifies to compress with fixed huffman codes.
500    ///
501    /// # Example
502    /// ```
503    /// use libflate::zlib::{Encoder, EncodeOptions};
504    ///
505    /// let options = EncodeOptions::new().fixed_huffman_codes();
506    /// let encoder = Encoder::with_options(Vec::new(), options).unwrap();
507    /// ```
508    pub fn fixed_huffman_codes(mut self) -> Self {
509        self.options = self.options.fixed_huffman_codes();
510        self
511    }
512
513    /// Specifies flush mode.
514    pub fn flush_mode(mut self, mode: FlushMode) -> Self {
515        self.flush_mode = mode;
516        self
517    }
518}
519
520/// ZLIB encoder.
521#[derive(Debug)]
522pub struct Encoder<W, E = lz77::DefaultLz77Encoder> {
523    header: Header,
524    flush_mode: FlushMode,
525    writer: deflate::Encoder<W, E>,
526    adler32: checksum::Adler32,
527}
528impl<W> Encoder<W, lz77::DefaultLz77Encoder>
529where
530    W: io::Write,
531{
532    /// Makes a new encoder instance.
533    ///
534    /// Encoded ZLIB stream is written to `inner`.
535    ///
536    /// # Examples
537    /// ```
538    /// #[cfg(feature = "std")]
539    /// use std::io::Write;
540    /// #[cfg(not(feature = "std"))]
541    /// use no_std_io2::io::Write;
542    /// use libflate::zlib::Encoder;
543    ///
544    /// let mut encoder = Encoder::new(Vec::new()).unwrap();
545    /// encoder.write_all(b"Hello World!").unwrap();
546    ///
547    /// assert_eq!(encoder.finish().into_result().unwrap(),
548    ///            vec![120, 156, 5, 192, 49, 13, 0, 0, 8, 3, 65, 43, 224, 6, 7, 24, 128,
549    ///                 237, 147, 38, 245, 63, 244, 230, 65, 181, 50, 215, 1, 28, 73, 4, 62]);
550    /// ```
551    pub fn new(inner: W) -> io::Result<Self> {
552        Self::with_options(inner, EncodeOptions::default())
553    }
554}
555impl<W, E> Encoder<W, E>
556where
557    W: io::Write,
558    E: lz77::Lz77Encode,
559{
560    /// Makes a new encoder instance with specified options.
561    ///
562    /// Encoded ZLIB stream is written to `inner`.
563    ///
564    /// # Examples
565    /// ```
566    /// use no_std_io2::io::Write;
567    /// use libflate::zlib::{Encoder, EncodeOptions};
568    ///
569    /// let options = EncodeOptions::new().no_compression();
570    /// let mut encoder = Encoder::with_options(Vec::new(), options).unwrap();
571    /// encoder.write_all(b"Hello World!").unwrap();
572    ///
573    /// assert_eq!(encoder.finish().into_result().unwrap(),
574    ///            [120, 1, 1, 12, 0, 243, 255, 72, 101, 108, 108, 111, 32, 87, 111,
575    ///             114, 108, 100, 33, 28, 73, 4, 62]);
576    /// ```
577    pub fn with_options(mut inner: W, options: EncodeOptions<E>) -> io::Result<Self> {
578        options.header.write_to(&mut inner)?;
579        Ok(Encoder {
580            header: options.header,
581            flush_mode: options.flush_mode,
582            writer: deflate::Encoder::with_options(inner, options.options),
583            adler32: checksum::Adler32::new(),
584        })
585    }
586
587    /// Returns the header of the ZLIB stream.
588    ///
589    /// # Examples
590    /// ```
591    /// use libflate::zlib::{Encoder, Lz77WindowSize};
592    ///
593    /// let encoder = Encoder::new(Vec::new()).unwrap();
594    /// assert_eq!(encoder.header().window_size(), Lz77WindowSize::KB32);
595    /// ```
596    pub fn header(&self) -> &Header {
597        &self.header
598    }
599
600    /// Writes the ZLIB trailer and returns the inner stream.
601    ///
602    /// # Examples
603    /// ```
604    /// use no_std_io2::io::Write;
605    /// use libflate::zlib::Encoder;
606    ///
607    /// let mut encoder = Encoder::new(Vec::new()).unwrap();
608    /// encoder.write_all(b"Hello World!").unwrap();
609    ///
610    /// assert_eq!(encoder.finish().into_result().unwrap(),
611    ///            vec![120, 156, 5, 192, 49, 13, 0, 0, 8, 3, 65, 43, 224, 6, 7, 24, 128,
612    ///                 237, 147, 38, 245, 63, 244, 230, 65, 181, 50, 215, 1, 28, 73, 4, 62]);
613    /// ```
614    ///
615    /// # Note
616    ///
617    /// If you are not concerned the result of this encoding,
618    /// it may be convenient to use `AutoFinishUnchecked` instead of the explicit invocation of this method.
619    ///
620    /// ```
621    /// use no_std_io2::io::Write;
622    /// use libflate::finish::AutoFinishUnchecked;
623    /// use libflate::zlib::Encoder;
624    ///
625    /// let plain = b"Hello World!";
626    /// let mut buf = Vec::new();
627    /// let mut encoder = AutoFinishUnchecked::new(Encoder::new(&mut buf).unwrap());
628    /// encoder.write_all(plain.as_ref()).unwrap();
629    /// ```
630    pub fn finish(self) -> Finish<W, io::Error> {
631        let mut inner = finish_try!(self.writer.finish());
632        match inner
633            .write_all(&self.adler32.value().to_be_bytes())
634            .and_then(|_| inner.flush())
635        {
636            Ok(_) => Finish::new(inner, None),
637            Err(e) => Finish::new(inner, Some(e)),
638        }
639    }
640
641    /// Returns the immutable reference to the inner stream.
642    pub fn as_inner_ref(&self) -> &W {
643        self.writer.as_inner_ref()
644    }
645
646    /// Returns the mutable reference to the inner stream.
647    pub fn as_inner_mut(&mut self) -> &mut W {
648        self.writer.as_inner_mut()
649    }
650
651    /// Unwraps the `Encoder`, returning the inner stream.
652    pub fn into_inner(self) -> W {
653        self.writer.into_inner()
654    }
655}
656impl<W, E> io::Write for Encoder<W, E>
657where
658    W: io::Write,
659    E: lz77::Lz77Encode,
660{
661    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
662        let written_size = self.writer.write(buf)?;
663        self.adler32.update(&buf[..written_size]);
664        Ok(written_size)
665    }
666    fn flush(&mut self) -> io::Result<()> {
667        match self.flush_mode {
668            FlushMode::None => self.writer.flush(),
669            FlushMode::Sync => self.writer.zlib_sync_flush(),
670        }
671    }
672}
673impl<W, E> Complete for Encoder<W, E>
674where
675    W: io::Write,
676    E: lz77::Lz77Encode,
677{
678    fn complete(self) -> io::Result<()> {
679        self.finish().into_result().map(|_| ())
680    }
681}
682
683#[cfg(test)]
684mod tests {
685    use super::*;
686    use crate::finish::AutoFinish;
687    use alloc::{borrow::ToOwned, string::ToString, vec, vec::Vec};
688    use no_std_io2::io::{Read as _, Write as _};
689
690    fn decode_all(buf: &[u8]) -> io::Result<Vec<u8>> {
691        let mut decoder = Decoder::new(buf).unwrap();
692        let mut buf = Vec::with_capacity(buf.len());
693        decoder.read_to_end(&mut buf)?;
694        Ok(buf)
695    }
696    fn default_encode(buf: &[u8]) -> io::Result<Vec<u8>> {
697        let mut encoder = Encoder::new(Vec::new()).unwrap();
698        encoder.write_all(buf).unwrap();
699        encoder.finish().into_result()
700    }
701    macro_rules! assert_encode_decode {
702        ($input:expr) => {{
703            let encoded = default_encode(&$input[..]).unwrap();
704            assert_eq!(decode_all(&encoded).unwrap(), &$input[..]);
705        }};
706    }
707
708    const DECODE_WORKS_TESTDATA: [u8; 20] = [
709        120, 156, 243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 81, 4, 0, 28, 73, 4, 62,
710    ];
711    #[test]
712    fn decode_works() {
713        let encoded = DECODE_WORKS_TESTDATA;
714        let mut decoder = Decoder::new(&encoded[..]).unwrap();
715        assert_eq!(
716            *decoder.header(),
717            Header {
718                window_size: Lz77WindowSize::KB32,
719                compression_level: CompressionLevel::Default,
720            }
721        );
722
723        let mut buf = Vec::new();
724        decoder.read_to_end(&mut buf).unwrap();
725
726        let expected = b"Hello World!";
727        assert_eq!(buf, expected);
728    }
729
730    #[test]
731    fn default_encode_works() {
732        let plain = b"Hello World! Hello ZLIB!!";
733        let mut encoder = Encoder::new(Vec::new()).unwrap();
734        encoder.write_all(plain.as_ref()).unwrap();
735        let encoded = encoder.finish().into_result().unwrap();
736        assert_eq!(decode_all(&encoded).unwrap(), plain);
737    }
738
739    #[test]
740    fn best_speed_encode_works() {
741        let plain = b"Hello World! Hello ZLIB!!";
742        let mut encoder =
743            Encoder::with_options(Vec::new(), EncodeOptions::default().fixed_huffman_codes())
744                .unwrap();
745        encoder.write_all(plain.as_ref()).unwrap();
746        let encoded = encoder.finish().into_result().unwrap();
747        assert_eq!(decode_all(&encoded).unwrap(), plain);
748    }
749
750    const RAW_ENCODE_WORKS_EXPECTED: [u8; 23] = [
751        120, 1, 1, 12, 0, 243, 255, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 28, 73,
752        4, 62,
753    ];
754    #[test]
755    fn raw_encode_works() {
756        let plain = b"Hello World!";
757        let mut encoder =
758            Encoder::with_options(Vec::new(), EncodeOptions::new().no_compression()).unwrap();
759        encoder.write_all(plain.as_ref()).unwrap();
760        let encoded = encoder.finish().into_result().unwrap();
761        let expected = RAW_ENCODE_WORKS_EXPECTED;
762        assert_eq!(encoded, expected);
763        assert_eq!(decode_all(&encoded).unwrap(), plain);
764    }
765
766    #[test]
767    fn encoder_auto_finish_works() {
768        let plain = b"Hello World! Hello ZLIB!!";
769        let mut buf = Vec::new();
770        {
771            let mut encoder = AutoFinish::new(Encoder::new(&mut buf).unwrap());
772            encoder.write_all(plain.as_ref()).unwrap();
773        }
774        assert_eq!(decode_all(&buf).unwrap(), plain);
775    }
776
777    #[test]
778    fn test_issue_2() {
779        // See: https://github.com/sile/libflate/issues/2
780        assert_encode_decode!([
781            163, 181, 167, 40, 62, 239, 41, 125, 189, 217, 61, 122, 20, 136, 160, 178, 119, 217,
782            217, 41, 125, 189, 97, 195, 101, 47, 170,
783        ]);
784        assert_encode_decode!([
785            162, 58, 99, 211, 7, 64, 96, 36, 57, 155, 53, 166, 76, 14, 238, 66, 66, 148, 154, 124,
786            162, 58, 99, 188, 138, 131, 171, 189, 54, 229, 192, 38, 29, 240, 122, 28,
787        ]);
788        assert_encode_decode!([
789            239, 238, 212, 42, 5, 46, 186, 67, 122, 247, 30, 61, 219, 62, 228, 202, 164, 205, 139,
790            109, 99, 181, 99, 181, 99, 122, 30, 12, 62, 46, 27, 145, 241, 183, 137,
791        ]);
792        assert_encode_decode!([
793            88, 202, 64, 12, 125, 108, 153, 49, 164, 250, 71, 19, 4, 108, 111, 108, 237, 205, 208,
794            77, 217, 100, 118, 49, 10, 64, 12, 125, 51, 202, 69, 67, 181, 146, 86,
795        ]);
796    }
797
798    #[test]
799    fn test_issues_16() {
800        // See: https://github.com/sile/libflate/issues/16
801
802        let encoded =
803            include_bytes!("../data/issues_16/crash-1bb6d408475a5bd57247ee40f290830adfe2086e");
804        assert_eq!(
805            &decode_all(&encoded[..])
806                .err()
807                .map(|e| e.to_string())
808                .unwrap()[..31],
809            "The value of HDIST is too big: max=30, actual=32"[..31]
810                .to_owned()
811                .as_str()
812        );
813
814        let encoded =
815            include_bytes!("../data/issues_16/crash-369e8509a0e76356f4549c292ceedee429cfe125");
816        assert_eq!(
817            &decode_all(&encoded[..])
818                .err()
819                .map(|e| e.to_string())
820                .unwrap()[..31],
821            "The value of HDIST is too big: max=30, actual=32"[..31]
822                .to_owned()
823                .as_str()
824        );
825
826        let encoded =
827            include_bytes!("../data/issues_16/crash-e75959d935650306881140df7f6d1d73e33425cb");
828        assert_eq!(
829            &decode_all(&encoded[..])
830                .err()
831                .map(|e| e.to_string())
832                .unwrap()[..31],
833            "The value of HDIST is too big: max=30, actual=32"[..31]
834                .to_owned()
835                .as_str()
836        );
837    }
838
839    #[test]
840    fn test_issues_27() {
841        // See: https://github.com/sile/libflate/issues/27
842
843        let writes = ["fooooooooooooooooo", "bar", "baz"];
844
845        // FlushMode::None
846        let mut encoder = Encoder::new(Vec::new()).unwrap();
847        for _ in 0..2 {
848            for string in &writes {
849                encoder.write(string.as_bytes()).expect("Write failed");
850            }
851            encoder.flush().expect("Flush failed");
852        }
853        let finished = encoder.finish().unwrap();
854        let expected = vec![
855            120, 156, // header
856            92, 192, 161, 17, 0, 0, 0, 1, 192, 89, 9, 170, 59, 209, 244, 186, 151, 31, 17, 162,
857            227, 2, 14, 141, 0, 0, 0, 8, 0, 206, 74, 80, 221, 137, 166, 215, 189, 252, 136, 16, 93,
858            1, 112, 32, 0, 0, 0, 0, 0, 228, 255, 26, 246, 95, 20, 111,
859        ];
860        assert_eq!(finished.0, expected);
861
862        let mut output = Vec::new();
863        Decoder::new(&finished.0[..])
864            .unwrap()
865            .read_to_end(&mut output)
866            .unwrap();
867        assert_eq!(
868            output,
869            "fooooooooooooooooobarbazfooooooooooooooooobarbaz".as_bytes()
870        );
871
872        // FlushMode::Sync
873        let mut encoder =
874            Encoder::with_options(Vec::new(), EncodeOptions::new().flush_mode(FlushMode::Sync))
875                .unwrap();
876        for _ in 0..2 {
877            for string in &writes {
878                encoder.write(string.as_bytes()).expect("Write failed");
879            }
880            encoder.flush().expect("Flush failed");
881        }
882        let finished = encoder.finish().unwrap();
883        let expected = vec![
884            120, 156, // header
885            92, 192, 161, 17, 0, 0, 0, 1, 192, 89, 9, 170, 59, 209, 244, 186, 151, 31, 17, 162, 3,
886            0, 0, 255, 255, // sync bytes
887            92, 192, 161, 17, 0, 0, 0, 1, 192, 89, 9, 170, 59, 209, 244, 186, 151, 31, 17, 162, 3,
888            0, 0, 255, 255, // sync bytes
889            5, 192, 129, 0, 0, 0, 0, 0, 144, 255, 107, 0, 246, 95, 20, 111,
890        ];
891        assert_eq!(finished.0, expected);
892
893        let mut output = Vec::new();
894        Decoder::new(&finished.0[..])
895            .unwrap()
896            .read_to_end(&mut output)
897            .unwrap();
898        assert_eq!(
899            output,
900            "fooooooooooooooooobarbazfooooooooooooooooobarbaz".as_bytes()
901        );
902    }
903
904    #[test]
905    #[cfg(feature = "std")]
906    /// See: https://github.com/sile/libflate/issues/61
907    fn issue_61() {
908        let data = default_encode(b"Hello World").unwrap();
909        let mut decoder = Decoder::new(&data[..]).unwrap();
910        let mut buf = Vec::new();
911        decoder.read(&mut buf).unwrap();
912        decoder.read_to_end(&mut buf).unwrap();
913        assert_eq!(buf, b"Hello World");
914    }
915
916    #[test]
917    fn issue71() {
918        let encoded_data = [
919            120, 218, 251, 255, 207, 144, 193, 138, 193, 151, 161, 146, 33, 143, 33, 149, 161, 156,
920            161, 24, 72, 38, 51, 148, 48, 100, 50, 228, 3, 69, 120, 25, 184, 24,
921        ];
922
923        let mut decoder = Decoder::new(&encoded_data[..]).unwrap();
924        let mut buf = Vec::new();
925        let result = decoder.read_to_end(&mut buf);
926        assert!(result.is_err());
927        buf.extend_from_slice(decoder.unread_decoded_data());
928
929        let decoded_data = [
930            255, 254, 49, 0, 58, 0, 77, 0, 121, 0, 110, 0, 101, 0, 119, 0, 115, 0, 101, 0, 99, 0,
931            116, 0, 105, 0, 111, 0, 110, 0, 13, 0, 10,
932        ];
933        assert_eq!(buf, decoded_data);
934    }
935
936    #[test]
937    #[cfg(feature = "std")]
938    fn issue_82() {
939        let encoded_data = [0x00, 0x00];
940        let error = Header::read_from(&encoded_data[..]).unwrap_err();
941        assert_eq!(error.kind(), io::ErrorKind::InvalidData);
942        assert!(error.to_string().contains("method=0"));
943    }
944}