Coverage Report

Created: 2026-09-28 07:16

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