1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
//! gzippy — embed the world's fastest gzip in your Rust program.
//!
//! Every function routes through the same backend-selection logic as the
//! gzippy CLI, so you automatically get ISA-L SIMD, libdeflate, parallel
//! multi-block, Zopfli, and multi-member decompression without any extra
//! configuration.
//!
//! # Quick start
//!
//! ```rust
//! let data = b"hello, world!".repeat(1000);
//! let compressed = gzippy::compress(&data, 6).unwrap();
//! let decompressed = gzippy::decompress(&compressed).unwrap();
//! assert_eq!(decompressed, data);
//! ```
//!
//! # Choosing a compression level
//!
//! | Level | Backend | Notes |
//! |-------|---------|-------|
//! | 0 | Store (no compression) | |
//! | 1–3 | ISA-L SIMD (x86_64), libdeflate/zlib-ng (other) | fastest |
//! | 4–5 | libdeflate one-shot | balanced |
//! | 6 | zlib-ng streaming | gzip default |
//! | 7–9 | zlib-ng streaming | high ratio |
//! | 10,12 | libdeflate ultra | near-zopfli ratio |
//! | 11 | Zopfli | best ratio, very slow |
//!
//! # Threading and output format
//!
//! `threads = 1` always produces a **standard single-member gzip** stream
//! decompressible by any tool.
//!
//! `threads > 1` behaviour depends on level:
//! - **L0–5**: [`ParallelGzEncoder`] produces a gzippy "GZ" multi-block
//! stream. This is **not** decompressible by standard tools (gunzip, pigz,
//! etc.) — only by gzippy itself (CLI or this library). Use it when both
//! ends of the pipe run gzippy.
//! - **L6–9**: [`PipelinedGzEncoder`] produces a standard single-member
//! stream that any tool can decompress.
//!
//! [`ParallelGzEncoder`]: compress::parallel::ParallelGzEncoder
//! [`PipelinedGzEncoder`]: compress::pipelined::PipelinedGzEncoder
//!
//! # Decompression
//!
//! The decompressor handles all gzip variants automatically:
//! - gzippy "GZ" multi-block streams (parallel bgzf path)
//! - Standard multi-member streams (e.g. `cat a.gz b.gz`)
//! - Single-member streams (standard gzip output)
//!
//! **Non-gzip input:** if `data` does not begin with the gzip magic bytes
//! (`0x1f 0x8b`), every decompress function returns `Ok(empty)` rather than
//! an error — consistent with CLI sniffing behavior.
// ── Shared infrastructure (same module tree as the binary) ───────────────────
// `compress::io` and `decompress::io` call `crate::set_output_file` to register
// the in-progress output path for signal-handler cleanup. In the library there
// is no signal handler, so this is a no-op.
// ── Engine modules ────────────────────────────────────────────────────────────
// `#[doc(hidden)]` marks these as internal: rustdoc will not render them,
// and the public contract is the six top-level functions + three types below.
// Items under `compress::` / `decompress::` are not covered by semver.
// ── Stable public surface ─────────────────────────────────────────────────────
pub use DecodePath;
pub use ;
// =============================================================================
// Compression API
// =============================================================================
/// Compress `data` to gzip format at `level` using all available CPUs.
///
/// `level` is clamped to `0..=12` (see the [level table](crate#choosing-a-compression-level)).
///
/// When all CPUs are used and `level` is in 0–5, the output uses gzippy's
/// parallel "GZ" multi-block format. Use [`compress_with_threads`]`(data, level, 1)`
/// if you need standard gzip output that any tool can read.
/// Compress `data` to gzip format at `level` using exactly `threads` threads.
///
/// **`threads = 1`** — standard single-member gzip; decompressible by any tool.
///
/// **`threads > 1, level 0–5`** — gzippy "GZ" multi-block format; only
/// decompressible by gzippy (CLI or this library). Faster for large inputs.
///
/// **`threads > 1, level 6–9`** — pipelined single-member gzip; any tool
/// can decompress.
/// Compress data from `reader` into `writer` at `level` using all available CPUs.
///
/// Suitable for large inputs you don't want to buffer entirely in memory. The
/// same threading and format rules as [`compress`] apply.
///
/// Returns the number of **uncompressed** bytes consumed from `reader`.
/// Compress data from `reader` into `writer` at `level` with explicit thread count.
///
/// The same threading and format rules as [`compress_with_threads`] apply.
///
/// Returns the number of **uncompressed** bytes consumed from `reader`.
// =============================================================================
// Decompression API
// =============================================================================
/// Decompress a gzip stream using all available CPUs.
///
/// Automatically selects the best path — parallel bgzf, parallel
/// multi-member, ISA-L single-member, or libdeflate one-shot — based on
/// the input format and available hardware.
///
/// **Non-gzip input:** returns `Ok(Vec::new())`.
/// Decompress a gzip stream with explicit thread count.
///
/// Set `threads = 1` for deterministic single-threaded decompression (useful
/// in constrained or benchmark contexts).
///
/// **Non-gzip input:** returns `Ok(Vec::new())`.
/// Decompress a gzip stream into `writer` using all available CPUs.
///
/// Useful when streaming output to a file or network socket without an
/// intermediate allocation. For explicit thread control use
/// [`decompress_to_writer_with_threads`].
///
/// Returns the number of decompressed bytes written.
///
/// **Non-gzip input:** writes nothing and returns `Ok(0)`.
/// Decompress a gzip stream into `writer` with explicit thread count.
///
/// Mirrors [`decompress_with_threads`] for the writer API.
///
/// Returns the number of decompressed bytes written.
///
/// **Non-gzip input:** writes nothing and returns `Ok(0)`.
// =============================================================================
// Raw DEFLATE API (no gzip framing)
// =============================================================================
/// Compress `data` to raw DEFLATE (RFC 1951) at `level` — no gzip header or trailer.
///
/// `level` is clamped to `0..=12`. Uses the same backend hierarchy as [`compress`]:
/// ISA-L SIMD on x86_64 for levels 0–3, then libdeflate one-shot for all levels.
///
/// Use this when the framing (CRC32, size) is handled by the caller, for example
/// when embedding deflate streams in ZIP, 7z, or zlib containers.
/// Decompress a raw DEFLATE stream (RFC 1951) — no gzip header or trailer expected.
///
/// Uses libdeflate for speed, growing the output buffer as needed. Falls back to
/// a flate2/zlib-ng streaming decoder if the output exceeds 1 GiB.
///
/// Returns an error if `data` is not valid DEFLATE.
/// Alias for [`compress_raw`] — used by 7zippy's Deflate coder.
pub use compress_raw as deflate_encode;
/// Alias for [`decompress_raw`].
pub use decompress_raw as deflate_decode;
// =============================================================================
// Deflate64 API (ZIP method 9 / Enhanced Deflate)
// =============================================================================
/// Decompress a raw Deflate64 stream (ZIP method 9 / Enhanced Deflate).
///
/// Deflate64 extends standard DEFLATE with a 64 KB sliding window,
/// length codes up to 65 538 bytes, and distance codes up to 65 536 bytes.
/// It is used as compression method 9 in ZIP archives.
///
/// `data` must be a raw Deflate64 bitstream — no ZIP local-file header,
/// no gzip framing. Returns the decompressed bytes.
///
/// Returns an error if `data` is not valid Deflate64.
/// Decompress a raw Deflate64 stream into `writer`.
///
/// Streaming variant of [`decompress_deflate64`] — avoids the intermediate
/// allocation when the caller already has a [`Write`] target.
///
/// Returns the number of decompressed bytes written.
/// Compress `data` as a raw Deflate64 bitstream, returning `Vec<u8>`.
///
/// Produces a valid Deflate64 (ZIP method 9 / Enhanced Deflate) raw stream.
/// No gzip or ZIP container is added.
/// Compress `data` as a raw Deflate64 bitstream, writing to `writer`.
///
/// Returns the number of compressed bytes written.
// =============================================================================
// Routing inspection
// =============================================================================
/// Return the [`DecodePath`] gzippy would choose for `data` with `threads`.
///
/// Useful for tests and diagnostics. Does not allocate or decompress.