Zstandard compression and decompression in safe Rust
mzstd is a port of the zstd 1.5.7 encoder that writes the same bytes, plus an independent Rust decoder. Reuse working memory between payloads, plug into Read and Write, drive either codec with your own buffers, and schedule parallel compression on your own threads.
A round trip
[dependencies]
mzstd = "0.2.13"
use mzstd::{Compressor, Decompressor, EncoderConfig, Level};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = "hello, smaller world! ".repeat(1000);
let mut encoder = Compressor::new(EncoderConfig::default().with_level(Level::try_from(3)?))?;
let compressed = encoder.compress(input.as_bytes())?;
let mut decoder = Decompressor::default();
assert_eq!(decoder.decompress(&compressed)?, input.as_bytes());
Ok(())
}
Requires Rust 1.89 or later. Getting started continues from here with memory reuse, streaming and feature selection.
Pick a level
The level trades speed for size; the default is 3. Each bar is the compressed size of the 211 MB Silesia corpus against its original size.
| Level | Compressed size | Compress | Decompress |
|---|---|---|---|
| -5 | 48.6% | 838 MB/s | 2828 MB/s |
| 1 | 34.5% | 626 MB/s | 1992 MB/s |
| 3 | 31.2% | 374 MB/s | 1784 MB/s |
| 8 | 28.2% | 103 MB/s | 1945 MB/s |
| 15 | 26.8% | 9.04 MB/s | 2014 MB/s |
| 22 | 24.7% | 2.27 MB/s | 1498 MB/s |
mzstd 0.2.12 in lzbench 2.4.1 on one thread of an AMD Ryzen 9 7950X VDS, fastest of three rounds. Your data and machine will differ.
See the lzbench run for the command and raw output, and benchmark results for every measured level against zstd 1.5.7, including the cases where mzstd is slower.
Find your path
no_std.
Decode untrusted inputWindow, input and output limits.
StreamingReaders, writers, sans-I/O sessions and finish.
Parallel compressionOne input across scoped threads, Rayon or your executor.
DictionariesRaw and trained dictionaries for small inputs.
Framing containers opt-inSeveral resources and metadata in one seekable container.
How it worksOwnership, dispatch and state machines, with diagrams.
What you can rely on
- Byte-identical encoder. For the same input and parameters, serial compression writes exactly the bytes of zstd 1.5.7. See what is claimed and how it is checked.
- Safe implementation, not a C wrapper. Production code forbids
unsafe; SIMD goes throughfearless_simd. The reference C library is only a test and benchmark oracle. - No hidden I/O or threads. Sessions touch only the buffers you pass in, and parallel compression hands tasks to your scheduler. The library does not create a thread pool.
- Reusable state. A codec keeps its workspace between payloads, under a retention policy you choose.
Framing requires the opt-in framed feature; its API may change in a patch
release.