1 //! A DEFLATE-based stream compression/decompression library
2 //!
3 //! This library provides support for compression and decompression of
4 //! DEFLATE-based streams:
5 //!
6 //! * the DEFLATE format itself
7 //! * the zlib format
8 //! * gzip
9 //!
10 //! These three formats are all closely related and largely only differ in their
11 //! headers/footers. This crate has three types in each submodule for dealing
12 //! with these three formats.
13 //!
14 //! # Implementation
15 //!
16 //! In addition to supporting three formats, this crate supports several different
17 //! backends, controlled through this crate's features:
18 //!
19 //! * `default`, or `rust_backend` - this implementation uses the `miniz_oxide`
20 //!   crate which is a port of `miniz.c` (below) to Rust. This feature does not
21 //!   require a C compiler and only requires Rust code.
22 //!
23 //! * `zlib` - this feature will enable linking against the `libz` library, typically found on most
24 //!   Linux systems by default. If the library isn't found to already be on the system it will be
25 //!   compiled from source (this is a C library).
26 //!
27 //! There's various tradeoffs associated with each implementation, but in general you probably
28 //! won't have to tweak the defaults. The default choice is selected to avoid the need for a C
29 //! compiler at build time. `zlib-ng-compat` is useful if you're using zlib for compatibility but
30 //! want performance via zlib-ng's zlib-compat mode. `zlib` is useful if something else in your
31 //! dependencies links the original zlib so you cannot use zlib-ng-compat. The compression ratios
32 //! and performance of each of these feature should be roughly comparable, but you'll likely want
33 //! to run your own tests if you're curious about the performance.
34 //!
35 //! # Organization
36 //!
37 //! This crate consists mainly of three modules, [`read`], [`write`], and
38 //! [`bufread`]. Each module contains a number of types used to encode and
39 //! decode various streams of data.
40 //!
41 //! All types in the [`write`] module work on instances of [`Write`][write],
42 //! whereas all types in the [`read`] module work on instances of
43 //! [`Read`][read] and [`bufread`] works with [`BufRead`][bufread]. If you
44 //! are decoding directly from a `&[u8]`, use the [`bufread`] types.
45 //!
46 //! ```
47 //! use flate2::write::GzEncoder;
48 //! use flate2::Compression;
49 //! use std::io;
50 //! use std::io::prelude::*;
51 //!
52 //! # fn main() { let _ = run(); }
53 //! # fn run() -> io::Result<()> {
54 //! let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
55 //! encoder.write_all(b"Example")?;
56 //! # Ok(())
57 //! # }
58 //! ```
59 //!
60 //!
61 //! Other various types are provided at the top-level of the crate for
62 //! management and dealing with encoders/decoders. Also note that types which
63 //! operate over a specific trait often implement the mirroring trait as well.
64 //! For example a `flate2::read::DeflateDecoder<T>` *also* implements the
65 //! `Write` trait if `T: Write`. That is, the "dual trait" is forwarded directly
66 //! to the underlying object if available.
67 //!
68 //! # About multi-member Gzip files
69 //!
70 //! While most `gzip` files one encounters will have a single *member* that can be read
71 //! with the [`GzDecoder`], there may be some files which have multiple members.
72 //!
73 //! A [`GzDecoder`] will only read the first member of gzip data, which may unexpectedly
74 //! provide partial results when a multi-member gzip file is encountered. `GzDecoder` is appropriate
75 //! for data that is designed to be read as single members from a multi-member file. `bufread::GzDecoder`
76 //! and `write::GzDecoder` also allow non-gzip data following gzip data to be handled.
77 //!
78 //! The [`MultiGzDecoder`] on the other hand will decode all members of a `gzip` file
79 //! into one consecutive stream of bytes, which hides the underlying *members* entirely.
80 //! If a file contains contains non-gzip data after the gzip data, MultiGzDecoder will
81 //! emit an error after decoding the gzip data. This behavior matches the `gzip`,
82 //! `gunzip`, and `zcat` command line tools.
83 //!
84 //! [`read`]: read/index.html
85 //! [`bufread`]: bufread/index.html
86 //! [`write`]: write/index.html
87 //! [read]: https://doc.rust-lang.org/std/io/trait.Read.html
88 //! [write]: https://doc.rust-lang.org/std/io/trait.Write.html
89 //! [bufread]: https://doc.rust-lang.org/std/io/trait.BufRead.html
90 //! [`GzDecoder`]: read/struct.GzDecoder.html
91 //! [`MultiGzDecoder`]: read/struct.MultiGzDecoder.html
92 #![doc(html_root_url = "https://docs.rs/flate2/0.2")]
93 #![deny(missing_docs)]
94 #![deny(missing_debug_implementations)]
95 #![allow(trivial_numeric_casts)]
96 #![cfg_attr(test, deny(warnings))]
97 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
98 
99 #[cfg(not(feature = "any_impl",))]
100 compile_error!("You need to choose a zlib backend");
101 
102 pub use crate::crc::{Crc, CrcReader, CrcWriter};
103 pub use crate::gz::GzBuilder;
104 pub use crate::gz::GzHeader;
105 pub use crate::mem::{Compress, CompressError, Decompress, DecompressError, Status};
106 pub use crate::mem::{FlushCompress, FlushDecompress};
107 
108 mod bufreader;
109 mod crc;
110 mod deflate;
111 mod ffi;
112 mod gz;
113 mod mem;
114 mod zio;
115 mod zlib;
116 
117 /// Types which operate over [`Read`] streams, both encoders and decoders for
118 /// various formats.
119 ///
120 /// Note that the `read` decoder types may read past the end of the compressed
121 /// data while decoding. If the caller requires subsequent reads to start
122 /// immediately following the compressed data  wrap the `Read` type in a
123 /// [`BufReader`] and use the `BufReader` with the equivalent decoder from the
124 /// `bufread` module and also for the subsequent reads.
125 ///
126 /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
127 /// [`BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.html
128 pub mod read {
129     pub use crate::deflate::read::DeflateDecoder;
130     pub use crate::deflate::read::DeflateEncoder;
131     pub use crate::gz::read::GzDecoder;
132     pub use crate::gz::read::GzEncoder;
133     pub use crate::gz::read::MultiGzDecoder;
134     pub use crate::zlib::read::ZlibDecoder;
135     pub use crate::zlib::read::ZlibEncoder;
136 }
137 
138 /// Types which operate over [`Write`] streams, both encoders and decoders for
139 /// various formats.
140 ///
141 /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
142 pub mod write {
143     pub use crate::deflate::write::DeflateDecoder;
144     pub use crate::deflate::write::DeflateEncoder;
145     pub use crate::gz::write::GzDecoder;
146     pub use crate::gz::write::GzEncoder;
147     pub use crate::gz::write::MultiGzDecoder;
148     pub use crate::zlib::write::ZlibDecoder;
149     pub use crate::zlib::write::ZlibEncoder;
150 }
151 
152 /// Types which operate over [`BufRead`] streams, both encoders and decoders for
153 /// various formats.
154 ///
155 /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
156 pub mod bufread {
157     pub use crate::deflate::bufread::DeflateDecoder;
158     pub use crate::deflate::bufread::DeflateEncoder;
159     pub use crate::gz::bufread::GzDecoder;
160     pub use crate::gz::bufread::GzEncoder;
161     pub use crate::gz::bufread::MultiGzDecoder;
162     pub use crate::zlib::bufread::ZlibDecoder;
163     pub use crate::zlib::bufread::ZlibEncoder;
164 }
165 
_assert_send_sync()166 fn _assert_send_sync() {
167     fn _assert_send_sync<T: Send + Sync>() {}
168 
169     _assert_send_sync::<read::DeflateEncoder<&[u8]>>();
170     _assert_send_sync::<read::DeflateDecoder<&[u8]>>();
171     _assert_send_sync::<read::ZlibEncoder<&[u8]>>();
172     _assert_send_sync::<read::ZlibDecoder<&[u8]>>();
173     _assert_send_sync::<read::GzEncoder<&[u8]>>();
174     _assert_send_sync::<read::GzDecoder<&[u8]>>();
175     _assert_send_sync::<read::MultiGzDecoder<&[u8]>>();
176     _assert_send_sync::<write::DeflateEncoder<Vec<u8>>>();
177     _assert_send_sync::<write::DeflateDecoder<Vec<u8>>>();
178     _assert_send_sync::<write::ZlibEncoder<Vec<u8>>>();
179     _assert_send_sync::<write::ZlibDecoder<Vec<u8>>>();
180     _assert_send_sync::<write::GzEncoder<Vec<u8>>>();
181     _assert_send_sync::<write::GzDecoder<Vec<u8>>>();
182 }
183 
184 /// When compressing data, the compression level can be specified by a value in
185 /// this struct.
186 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
187 pub struct Compression(u32);
188 
189 impl Compression {
190     /// Creates a new description of the compression level with an explicitly
191     /// specified integer.
192     ///
193     /// The integer here is typically on a scale of 0-9 where 0 means "no
194     /// compression" and 9 means "take as long as you'd like".
new(level: u32) -> Compression195     pub const fn new(level: u32) -> Compression {
196         Compression(level)
197     }
198 
199     /// No compression is to be performed, this may actually inflate data
200     /// slightly when encoding.
none() -> Compression201     pub const fn none() -> Compression {
202         Compression(0)
203     }
204 
205     /// Optimize for the best speed of encoding.
fast() -> Compression206     pub const fn fast() -> Compression {
207         Compression(1)
208     }
209 
210     /// Optimize for the size of data being encoded.
best() -> Compression211     pub const fn best() -> Compression {
212         Compression(9)
213     }
214 
215     /// Returns an integer representing the compression level, typically on a
216     /// scale of 0-9
level(&self) -> u32217     pub fn level(&self) -> u32 {
218         self.0
219     }
220 }
221 
222 impl Default for Compression {
default() -> Compression223     fn default() -> Compression {
224         Compression(6)
225     }
226 }
227 
228 #[cfg(test)]
random_bytes() -> impl Iterator<Item = u8>229 fn random_bytes() -> impl Iterator<Item = u8> {
230     use rand::Rng;
231     use std::iter;
232 
233     iter::repeat(()).map(|_| rand::thread_rng().gen())
234 }
235