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