| 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 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 |  | 
|---|
| 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". | 
|---|
| 195 | /// | 
|---|
| 196 | /// ### Backend differences | 
|---|
| 197 | /// | 
|---|
| 198 | /// The [`miniz_oxide`](https://crates.io/crates/miniz_oxide) backend for flate2 | 
|---|
| 199 | /// does not support level 0 or `Compression::none()`. Instead it interprets them | 
|---|
| 200 | /// as the default compression level, which is quite slow. | 
|---|
| 201 | /// `Compression::fast()` should be used instead. | 
|---|
| 202 | /// | 
|---|
| 203 | /// `miniz_oxide` also supports a non-compliant compression level 10. | 
|---|
| 204 | /// It is even slower and may result in higher compression, but | 
|---|
| 205 | /// **only miniz_oxide will be able to read the data** compressed with level 10. | 
|---|
| 206 | /// Do **not** use level 10 if you need other software to be able to read it! | 
|---|
| 207 | pub const fn new(level: u32) -> Compression { | 
|---|
| 208 | Compression(level) | 
|---|
| 209 | } | 
|---|
| 210 |  | 
|---|
| 211 | /// No compression is to be performed, this may actually inflate data | 
|---|
| 212 | /// slightly when encoding. | 
|---|
| 213 | pub const fn none() -> Compression { | 
|---|
| 214 | Compression(0) | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | /// Optimize for the best speed of encoding. | 
|---|
| 218 | pub const fn fast() -> Compression { | 
|---|
| 219 | Compression(1) | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|
| 222 | /// Optimize for the size of data being encoded. | 
|---|
| 223 | pub const fn best() -> Compression { | 
|---|
| 224 | Compression(9) | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 | /// Returns an integer representing the compression level, typically on a | 
|---|
| 228 | /// scale of 0-9. See [`new`](Self::new) for details about compression levels. | 
|---|
| 229 | pub fn level(&self) -> u32 { | 
|---|
| 230 | self.0 | 
|---|
| 231 | } | 
|---|
| 232 | } | 
|---|
| 233 |  | 
|---|
| 234 | impl Default for Compression { | 
|---|
| 235 | fn default() -> Compression { | 
|---|
| 236 | Compression(6) | 
|---|
| 237 | } | 
|---|
| 238 | } | 
|---|
| 239 |  | 
|---|
| 240 | #[ cfg(test)] | 
|---|
| 241 | fn random_bytes() -> impl Iterator<Item = u8> { | 
|---|
| 242 | use rand::Rng; | 
|---|
| 243 | use std::iter; | 
|---|
| 244 |  | 
|---|
| 245 | iter::repeat(()).map(|_| rand::thread_rng().gen()) | 
|---|
| 246 | } | 
|---|
| 247 |  | 
|---|