Coverage Report

Created: 2026-02-14 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flate2-1.1.9/src/lib.rs
Line
Count
Source
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 flags*:
18
//!
19
//! * `default`, or `rust_backend` - this implementation currently uses the `miniz_oxide`
20
//!   crate which is a port of `miniz.c` to Rust. This feature does not
21
//!   require a C compiler, and only uses safe Rust code.
22
//!
23
//!   Note that the `rust_backend` feature may at some point be switched to use `zlib-rs`,
24
//!   and that `miniz_oxide` should be used explicitly if this is not desired.
25
//!
26
//! * `zlib-rs` - this implementation utilizes the `zlib-rs` crate, a Rust rewrite of zlib.
27
//!   This backend is the fastest, at the cost of some `unsafe` Rust code.
28
//!
29
//! Several backends implemented in C are also available.
30
//! These are useful in case you are already using a specific C implementation
31
//! and need the result of compression to be bit-identical.
32
//! See the crate's README for details on the available C backends.
33
//!
34
//! The `zlib-rs` backend typically outperforms all the C implementations.
35
//!
36
//! # Feature Flags
37
#![cfg_attr(
38
    not(feature = "document-features"),
39
    doc = "Activate the `document-features` cargo feature to see feature docs here"
40
)]
41
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
42
//!
43
//! ## Ambiguous feature selection
44
//!
45
//! As Cargo features are additive, while backends are not, there is an order in which backends
46
//! become active if multiple are selected.
47
//!
48
//! * zlib-ng
49
//! * zlib-rs
50
//! * cloudflare_zlib
51
//! * miniz_oxide
52
//!
53
//! # Organization
54
//!
55
//! This crate consists of three main modules: `bufread`, `read`, and `write`. Each module
56
//! implements DEFLATE, zlib, and gzip for [`std::io::BufRead`] input types, [`std::io::Read`] input
57
//! types, and [`std::io::Write`] output types respectively.
58
//!
59
//! Use the [`mod@bufread`] implementations if you can provide a `BufRead` type for the input.
60
//! The `&[u8]` slice type implements the `BufRead` trait.
61
//!
62
//! The [`mod@read`] implementations conveniently wrap a `Read` type in a `BufRead` implementation.
63
//! However, the `read` implementations may
64
//! [read past the end of the input data](https://github.com/rust-lang/flate2-rs/issues/338),
65
//! making the `Read` type useless for subsequent reads of the input. If you need to re-use the
66
//! `Read` type, wrap it in a [`std::io::BufReader`], use the `bufread` implementations,
67
//! and perform subsequent reads on the `BufReader`.
68
//!
69
//! The [`mod@write`] implementations are most useful when there is no way to create a `BufRead`
70
//! type, notably when reading async iterators (streams).
71
//!
72
//! ```
73
//! use futures::{Stream, StreamExt};
74
//! use std::io::{Result, Write as _};
75
//!
76
//! async fn decompress_gzip_stream<S, I>(stream: S) -> Result<Vec<u8>>
77
//! where
78
//!     S: Stream<Item = I>,
79
//!     I: AsRef<[u8]>
80
//! {
81
//!     let mut stream = std::pin::pin!(stream);
82
//!     let mut w = Vec::<u8>::new();
83
//!     let mut decoder = flate2::write::GzDecoder::new(w);
84
//!     while let Some(input) = stream.next().await {
85
//!         decoder.write_all(input.as_ref())?;
86
//!     }
87
//!     decoder.finish()
88
//! }
89
//! ```
90
//!
91
//!
92
//! Note that types which operate over a specific trait often implement the mirroring trait as well.
93
//! For example a `bufread::DeflateDecoder<T>` *also* implements the
94
//! [`Write`] trait if `T: Write`. That is, the "dual trait" is forwarded directly
95
//! to the underlying object if available.
96
//!
97
//! # About multi-member Gzip files
98
//!
99
//! While most `gzip` files one encounters will have a single *member* that can be read
100
//! with the [`GzDecoder`], there may be some files which have multiple members.
101
//!
102
//! A [`GzDecoder`] will only read the first member of gzip data, which may unexpectedly
103
//! provide partial results when a multi-member gzip file is encountered. `GzDecoder` is appropriate
104
//! for data that is designed to be read as single members from a multi-member file. `bufread::GzDecoder`
105
//! and `write::GzDecoder` also allow non-gzip data following gzip data to be handled.
106
//!
107
//! The [`MultiGzDecoder`] on the other hand will decode all members of a `gzip` file
108
//! into one consecutive stream of bytes, which hides the underlying *members* entirely.
109
//! If a file contains non-gzip data after the gzip data, MultiGzDecoder will
110
//! emit an error after decoding the gzip data. This behavior matches the `gzip`,
111
//! `gunzip`, and `zcat` command line tools.
112
//!
113
//! [`Bufread`]: std::io::BufRead
114
//! [`BufReader`]: std::io::BufReader
115
//! [`Read`]: std::io::Read
116
//! [`Write`]: std::io::Write
117
//! [`GzDecoder`]: bufread::GzDecoder
118
//! [`MultiGzDecoder`]: bufread::MultiGzDecoder
119
#![doc(html_root_url = "https://docs.rs/flate2/0.2")]
120
#![deny(missing_docs)]
121
#![deny(missing_debug_implementations)]
122
#![allow(trivial_numeric_casts)]
123
#![cfg_attr(test, deny(warnings))]
124
#![cfg_attr(docsrs, feature(doc_cfg))]
125
126
#[cfg(not(feature = "any_impl",))]
127
compile_error!("You need to choose a zlib backend");
128
129
pub use crate::crc::{Crc, CrcReader, CrcWriter};
130
pub use crate::gz::GzBuilder;
131
pub use crate::gz::GzHeader;
132
pub use crate::mem::{Compress, CompressError, Decompress, DecompressError, Status};
133
pub use crate::mem::{FlushCompress, FlushDecompress};
134
135
mod bufreader;
136
mod crc;
137
mod deflate;
138
mod ffi;
139
mod gz;
140
mod mem;
141
mod zio;
142
mod zlib;
143
144
/// Types which operate over [`Read`] streams, both encoders and decoders for
145
/// various formats.
146
///
147
/// Note that the `read` decoder types may read past the end of the compressed
148
/// data while decoding. If the caller requires subsequent reads to start
149
/// immediately following the compressed data  wrap the `Read` type in a
150
/// [`BufReader`] and use the `BufReader` with the equivalent decoder from the
151
/// `bufread` module and also for the subsequent reads.
152
///
153
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
154
/// [`BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.html
155
pub mod read {
156
    pub use crate::deflate::read::DeflateDecoder;
157
    pub use crate::deflate::read::DeflateEncoder;
158
    pub use crate::gz::read::GzDecoder;
159
    pub use crate::gz::read::GzEncoder;
160
    pub use crate::gz::read::MultiGzDecoder;
161
    pub use crate::zlib::read::ZlibDecoder;
162
    pub use crate::zlib::read::ZlibEncoder;
163
}
164
165
/// Types which operate over [`Write`] streams, both encoders and decoders for
166
/// various formats.
167
///
168
/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
169
pub mod write {
170
    pub use crate::deflate::write::DeflateDecoder;
171
    pub use crate::deflate::write::DeflateEncoder;
172
    pub use crate::gz::write::GzDecoder;
173
    pub use crate::gz::write::GzEncoder;
174
    pub use crate::gz::write::MultiGzDecoder;
175
    pub use crate::zlib::write::ZlibDecoder;
176
    pub use crate::zlib::write::ZlibEncoder;
177
}
178
179
/// Types which operate over [`BufRead`] streams, both encoders and decoders for
180
/// various formats.
181
///
182
/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
183
pub mod bufread {
184
    pub use crate::deflate::bufread::DeflateDecoder;
185
    pub use crate::deflate::bufread::DeflateEncoder;
186
    pub use crate::gz::bufread::GzDecoder;
187
    pub use crate::gz::bufread::GzEncoder;
188
    pub use crate::gz::bufread::MultiGzDecoder;
189
    pub use crate::zlib::bufread::ZlibDecoder;
190
    pub use crate::zlib::bufread::ZlibEncoder;
191
}
192
193
0
fn _assert_send_sync() {
194
0
    fn _assert_send_sync<T: Send + Sync>() {}
195
196
0
    _assert_send_sync::<read::DeflateEncoder<&[u8]>>();
197
0
    _assert_send_sync::<read::DeflateDecoder<&[u8]>>();
198
0
    _assert_send_sync::<read::ZlibEncoder<&[u8]>>();
199
0
    _assert_send_sync::<read::ZlibDecoder<&[u8]>>();
200
0
    _assert_send_sync::<read::GzEncoder<&[u8]>>();
201
0
    _assert_send_sync::<read::GzDecoder<&[u8]>>();
202
0
    _assert_send_sync::<read::MultiGzDecoder<&[u8]>>();
203
0
    _assert_send_sync::<write::DeflateEncoder<Vec<u8>>>();
204
0
    _assert_send_sync::<write::DeflateDecoder<Vec<u8>>>();
205
0
    _assert_send_sync::<write::ZlibEncoder<Vec<u8>>>();
206
0
    _assert_send_sync::<write::ZlibDecoder<Vec<u8>>>();
207
0
    _assert_send_sync::<write::GzEncoder<Vec<u8>>>();
208
0
    _assert_send_sync::<write::GzDecoder<Vec<u8>>>();
209
0
}
210
211
/// When compressing data, the compression level can be specified by a value in
212
/// this struct.
213
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
214
pub struct Compression(u32);
215
216
impl Compression {
217
    /// Creates a new description of the compression level with an explicitly
218
    /// specified integer.
219
    ///
220
    /// The integer here is typically on a scale of 0-9 where 0 means "no
221
    /// compression" and 9 means "take as long as you'd like".
222
0
    pub const fn new(level: u32) -> Compression {
223
0
        Compression(level)
224
0
    }
225
226
    /// No compression is to be performed, this may actually inflate data
227
    /// slightly when encoding.
228
0
    pub const fn none() -> Compression {
229
0
        Compression(0)
230
0
    }
231
232
    /// Optimize for the best speed of encoding.
233
0
    pub const fn fast() -> Compression {
234
0
        Compression(1)
235
0
    }
236
237
    /// Optimize for the size of data being encoded.
238
0
    pub const fn best() -> Compression {
239
0
        Compression(9)
240
0
    }
241
242
    /// Returns an integer representing the compression level, typically on a
243
    /// scale of 0-9. See [`new`](Self::new) for details about compression levels.
244
0
    pub fn level(&self) -> u32 {
245
0
        self.0
246
0
    }
247
}
248
249
impl Default for Compression {
250
0
    fn default() -> Compression {
251
0
        Compression(6)
252
0
    }
253
}
254
255
#[cfg(test)]
256
fn random_bytes() -> impl Iterator<Item = u8> {
257
    use rand::Rng;
258
    use std::iter;
259
260
    iter::repeat(()).map(|_| rand::rng().random())
261
}