noflate
A no_std sans-io DEFLATE / ZLIB / GZIP encoder and decoder with no dependencies.
Features
- No dependencies; pure, portable, safe Rust (
#![forbid(unsafe_code)]) no_stdcompatible by default (requiresalloc; no feature flag needed)- Sans-I/O streaming API — the library owns its buffers; the caller feeds bytes in and pulls bytes out. No
std::io::Read/std::io::Writecoupling, no implicit I/O. - DEFLATE (RFC 1951): encoder and decoder, all three block kinds (stored / fixed Huffman / dynamic Huffman)
- ZLIB (RFC 1950) wrapper with Adler-32 verification
- GZIP (RFC 1952) wrapper with CRC-32 + ISIZE verification
Examples
One-shot DEFLATE
let input = b"Hello, DEFLATE!";
let compressed = compress.unwrap;
let decompressed = decompress.unwrap;
assert_eq!;
Streaming decoder
let compressed = compress.unwrap;
let mut decoder = new;
decoder.feed.unwrap;
assert!;
let out = decoder.output.to_vec;
decoder.advance;
assert_eq!;
zlib / gzip
let gz = compress.unwrap;
assert_eq!;
let zl = compress.unwrap;
assert_eq!;
Benchmarks
The repository ships two benchmark binaries:
BENCH_REPEATS=30
BENCH_REPEATS=30
The numbers below are rough indicators only — throughput fluctuates substantially with hardware, runner load, workload size, and specific input. Depending on the environment, noflate can be faster or slower than flate2 on the same operation. Re-run the Benchmark workflow (Actions → Benchmark → Run workflow) or run the examples locally before making performance-sensitive decisions.
- Source: GitHub Actions, standard runners
ubuntu-latest: AMD EPYC 7763 (2 vCPU, x86_64, Azure)macos-latest: Apple M1 Virtual (3 vCPU, arm64)
- Toolchain:
rustc 1.94.1,--release - Methodology:
BENCH_REPEATS=30, best-of reported; encode throughput is of the raw input stream, decode throughput is of the decompressed output stream
DEFLATE, 1 MiB English text (MB/s):
| noflate (ubuntu) | flate2 (ubuntu) | noflate (macos) | flate2 (macos) | |
|---|---|---|---|---|
| encode | 402 | 363 | 603 | 994 |
| decode | 1839 | 3230 | 4743 | 3019 |
Encode compression ratio (compressed / original — deterministic, identical across runners):
| input | noflate | flate2 |
|---|---|---|
| english 1 KiB | 0.1494 | 0.1504 |
| english 64 KiB | 0.0064 | 0.0065 |
| english 1 MiB | 0.0040 | 0.0040 |
| zeros 64 KiB | 0.0012 | 0.0012 |
| random 64 KiB | 1.0011 | 1.0002 |
Noflate's ratio is within ~0.1 % of flate2 across the board — slightly better on short text (more thorough length-limited Huffman), slightly worse on ultra-short stored payloads (e.g. 64 KiB of zeros: 79 bytes vs 78 bytes) and on incompressible input.
Checksums of 1 MiB (MB/s):
| noflate (ubuntu) | reference (ubuntu) | noflate (macos) | reference (macos) | |
|---|---|---|---|---|
| CRC-32 | 2258 | 11510 (crc32fast) |
3053 | 7959 (crc32fast) |
| Adler-32 | 3038 | 3004 (adler32) |
2849 | 2662 (adler32) |
Notes on these numbers:
- The DEFLATE decoder is usually faster than
flate2on text — but not always. The 1 MiB case on the Ubuntu runner is the exception (1.8× slower); smaller sizes and random data favour noflate. See the raw workflow logs for the full matrix. - The DEFLATE encoder is within ~2× of
flate2on long text; per-call setup cost dominates near 1 KiB inputs (4–5× slower there). - Adler-32 matches the
adler32crate on both runners. - CRC-32 is 2.5×–5× slower than
crc32fast's PCLMULQDQ path — the price of staying portable, safe (#![forbid(unsafe_code)]), and free of CPU-specific intrinsics.