Expand description
Pure-Rust Zstandard (RFC 8878) codec.
The crate README is the module documentation, so its examples are compiled
and run by cargo test --doc – an install guide that cannot go stale.
§rusty_zstd
A ground-up, pure-Rust Zstandard (RFC 8878) compressor and decompressor.
#![deny(unsafe_code)]everywhere but one audited SIMD island, zero dependencies, no C, no*-syscrate, no FFI. Every frame it emits decompresses in facebook/zstd v1.5.7 and every frame that emits decompresses here — dual-gated on the Silesia corpus every commit.
Part of Remade With Rust by Mata Network. Full README, benchmark boards and methodology: the repository.
§Install
cargo add rusty_zstd[dependencies]
rusty_zstd = "0.1"
# …or for embedded / wasm targets with no `std`:
rusty_zstd = { version = "0.1", default-features = false, features = ["alloc"] }The minimum supported configuration is no_std + alloc — every entry point
returns or fills a Vec, so alloc is required. MSRV is 1.85.
| Feature | Default | What it adds |
|---|---|---|
std | ✅ | std::io-shaped streaming, multi-threading, the trainer, runtime ISA dispatch |
alloc | ✅ | implied by std; the minimum supported configuration |
profile | the in-process stage profiler and its counters (off = zero overhead) |
§Quick start
use rusty_zstd::{compress, decompress, DEFAULT_CLEVEL};
let data = b"the quick brown fox jumps over the lazy dog ".repeat(64);
let packed = compress(&data, DEFAULT_CLEVEL)?; // level 3, as libzstd defaults
assert!(packed.len() < data.len());
assert_eq!(decompress(&packed)?, data); // lossless, alwaysLevels run −7…22 with all nine libzstd strategies behind them.
compress_with takes a CompressOptions for the checksum flag, content size and
dictionary ID; compress_with_advanced exposes the full AdvancedOptions —
window log, strategy, LDM, workers, job size, overlap.
Streaming, for data that does not fit in memory. The pump is libzstd-shaped: hand it an input slice and an output buffer, and it reports what it consumed and produced.
use rusty_zstd::{compress_stream_out_size, Compressor, Flush};
let mut enc = Compressor::new(3)?;
let mut out = Vec::new();
let mut buf = vec![0u8; compress_stream_out_size()];
for chunk in [b"first chunk ".as_slice(), b"second chunk".as_slice()] {
let mut fed = 0;
while fed < chunk.len() {
let st = enc.stream(&chunk[fed..], &mut buf, Flush::Continue)?;
fed += st.input_consumed;
out.extend_from_slice(&buf[..st.output_produced]);
}
}
loop {
let st = enc.stream(&[], &mut buf, Flush::End)?;
out.extend_from_slice(&buf[..st.output_produced]);
if st.done {
break;
}
}
assert_eq!(rusty_zstd::decompress(&out)?, b"first chunk second chunk");Dictionaries, trained from your own samples — the win that matters for many small records:
use rusty_zstd::{compress_using_dict, decompress_using_dict, train, Dictionary, TrainOptions};
let samples: Vec<Vec<u8>> = (0..256)
.map(|i| format!("{{\"event\":\"click\",\"id\":{i},\"session\":\"abc123\"}}").into_bytes())
.collect();
let refs: Vec<&[u8]> = samples.iter().map(|s| s.as_slice()).collect();
let raw = train(&refs, TrainOptions::default())?; // fastcover, d=8 steps=4
let dict = Dictionary::from_bytes(&raw)?;
let packed = compress_using_dict(&samples[0], &dict, 3)?;
assert_eq!(decompress_using_dict(&packed, &dict)?, samples[0]);§What is in here
| Area | Surface |
|---|---|
| One-shot | compress, decompress, decompress_into, compress_bound, content_size, find_frame_compressed_size |
| Options | CompressOptions, AdvancedOptions, DecompressOptions, CompressionParameters, Strategy |
| Streaming | Compressor, Decompressor, Flush, StreamStatus, and the four recommended-buffer-size helpers |
| Dictionaries | Dictionary, compress_using_dict, decompress_using_dict, compress_using_prefix (patch-from), train + TrainOptions / TrainAlgo |
| Long-range | LdmParams, DEFAULT_LONG_WINDOW_LOG |
| Seekable | compress_seekable, decompress_frame_at, parse_seek_table, SeekTable, SeekEntry |
| Multi-thread | compress_mt, default_nb_workers, resolve_job_size, overlap_size |
| Inspection | get_frame_header, FrameHeader, FrameKind, inspect_frames, ListedFrame |
| Checksum | xxh64 — the frame content hash, usable on its own |
Items marked #[doc(hidden)] are campaign instrumentation for the repository’s
own benchmark harness. They carry no semver promise and may be renamed or
removed in any release.
§Correctness
Gated against facebook/zstd v1.5.7 as an external process, in both
directions, every commit: C compresses → this decompresses bit-exact, and this
compresses → C’s zstd -t and zstd -d accept it. The XXH64 checksum is gated
against the published vectors, and every SIMD kernel against its scalar twin.
§License
MIT OR Apache-2.0, at your option. No GPL/LGPL and no C anywhere in the
dependency tree — CI-enforced with cargo-deny.
Structs§
- Advanced
Options - Extra compressor knobs: LDM (
--long),--rsyncable, target cblock size, MT. - Compress
Options - Knobs for
compress_with. - Compression
Parameters - libzstd
ZSTD_compressionParametersfor a level and size hint. - Compressor
- Reusable compressor (one frame at a time).
- Decompress
Options - Decoder knobs for
decompress_with. - Decompressor
- Reusable decompressor. Multi-frame. Window-bounded history.
- Dictionary
- A zstd dictionary (raw bytes or trained with entropy tables).
- Frame
Header - Parsed Zstandard frame header (not skippable).
- InProcess
Bench - In-process compress + decompress at a compression level.
- LdmParams
- LDM knobs (
ZSTD_c_ldm*). Zero means “pick C-like defaults from windowLog”. - Listed
Frame - One frame in a concatenated stream (
-l/inspect_frames). - Loop
Timing - Wall timing of a looped closure (the shared timer).
- Seek
Entry - One seek-table row.
- Seek
Table - Parsed seek table (does not include the skippable header itself).
- Stream
Status - Bytes moved by one
Compressor::stream/Decompressor::streamcall. - Train
Options - Knobs for
train.
Enums§
- Error
- Codec error. Stable kinds only.
- Flush
ZSTD_EndDirective.- Frame
Kind - First frame at
src: a Zstd frame or a skippable frame. - Strategy
- Match finder (libzstd
ZSTD_strategy, values 1..=9). - Train
Algo - Trainer algorithm.
Constants§
- BLOCKSIZE_
MAX - RFC 8878 / libzstd
ZSTD_BLOCKSIZE_MAX. - DEFAULT_
CLEVEL - Default compression level (matches libzstd
ZSTD_CLEVEL_DEFAULT). - DEFAULT_
FRAME_ SIZE - Default independent-frame size (
--seekable). - DEFAULT_
LONG_ WINDOW_ LOG - Default
--longwindowLog (libzstdZSTD_WINDOWLOG_LIMIT_DEFAULTpath: 27). - DEFAULT_
MAX_ DICT - Default
--maxdict(110 KiB), matching libzstd. - DEFAULT_
WINDOW_ MAX - Default decoder window cap (CLI
-Mdefault): 128 MiB. - DICT_
ID_ PUBLIC_ MAX - Public Dictionary_IDs are below 2^31.
- DICT_
ID_ PUBLIC_ MIN - Minimum public Dictionary_ID (RFC 8878 reserved below this).
- JOB_
SIZE_ MIN - Transparent minimum job size (512 KiB), unless overlap is larger.
- MAGIC
- Zstandard frame magic (little-endian
0xFD2FB528). - MAGIC_
DICTIONARY - Trained dictionary magic (little-endian
0xEC30A437). - MAGIC_
SKIPPABLE_ MAX - Last skippable magic (
0x184D2A5F). - MAGIC_
SKIPPABLE_ MIN - First skippable magic (
0x184D2A50). - MAX_
CLEVEL - Maximum compression level (matches libzstd
--ultra22). - MIN_
CLEVEL - Minimum negative compression level (matches libzstd
ZSTD_minCLevel). - NB_
WORKERS_ MAX - libzstd
ZSTDMT_NBWORKERS_MAXon 64-bit. - SEEKABLE_
MAGIC - Seek table footer magic (
0x8F92EAB1). - SEEKABLE_
SKIPPABLE_ MAGIC - Skippable magic used by the seek table frame (
0x184D2A5E). - VERSION
- Library version (semver of this crate, not the zstd format).
Functions§
- bench_
roundtrip - Oneshot
compress+decompressatlevel, timed as two separate phases. Checksdecode(encode(x)) == xonce, outside both timed regions. - bench_
roundtrip_ clocked bench_roundtripwith an injected monotonic tick source.- compress
- One-shot compress at
level(-7..=22). Checksum on, content size in the header. - compress_
bound - Worst-case compressed size for a single-pass frame (libzstd
ZSTD_compressBound). - compress_
mt - Compress
srcas concatenated independent frames, optionally in parallel. - compress_
seekable - Compress
srcas independent frames plus a trailing seek table. - compress_
seekable_ adv compress_seekablewith LDM / rsyncable / target-cblock knobs.- compress_
stream_ in_ size - Recommended input chunk (
ZSTD_CStreamInSize). - compress_
stream_ out_ size - Recommended output chunk (
ZSTD_CStreamOutSize). - compress_
using_ dict - Compress
srcusing a dictionary (raw or trained). - compress_
using_ dict_ with - Compress with a dictionary and explicit checksum / Dictionary_ID knobs.
- compress_
using_ prefix - Compress
srcwith an external prefix (--patch-from/ZSTD_CCtx_refPrefix). No Dictionary_ID is written. - compress_
with - One-shot compress with explicit options.
- compress_
with_ advanced compress_with_historyplus LDM / rsyncable / target-cblock.- compress_
with_ history - One-shot compress with an optional dictionary or prefix (
-D/--patch-from). - compress_
with_ params - One-shot compress with already-resolved compression parameters (
--zstd=). - compression_
params - Parameters C would pick at
levelfor an optional size hint (None= unknown / large). - content_
size - Frame_Content_Size of the first Zstd frame, skipping leading skippable frames.
Nonemeans the size was not present in the header. - decompress
- One-shot decompress of one or more concatenated frames (skippable frames ignored).
- decompress_
frame_ at - Decompress the independent frame covering uncompressed
offset(one frame). - decompress_
into - Decompress into a caller-owned buffer, appending. Returns bytes written.
- decompress_
into_ with decompress_intowith an explicit window cap.- decompress_
stream_ in_ size - Recommended decompress input chunk (
ZSTD_DStreamInSize). - decompress_
stream_ out_ size - Recommended decompress output chunk (
ZSTD_DStreamOutSize). - decompress_
using_ dict - One-shot decompress using a dictionary (
ZSTD_decompress_usingDict). - decompress_
using_ dict_ with decompress_using_dictwith an explicit window cap (-d --long).- decompress_
using_ prefix - One-shot decompress using a prefix (
ZSTD_decompress_usingDDict/--patch-from). - decompress_
using_ prefix_ with decompress_using_prefixwith an explicit window cap.- decompress_
with - One-shot decompress with an explicit window cap.
- default_
nb_ workers std::thread::available_parallelism, clamped to1..=NB_WORKERS_MAX(-T0).- default_
overlap_ log - Default
--overlap-logwhen the caller passes 0 (zstdman: 6..=9 by strategy). - find_
frame_ compressed_ size - Byte length of the first frame (Zstd or skippable), including checksum.
- get_
frame_ header - Parse the first frame header (skippable or zstd). Does not consume blocks.
- inspect_
frames - Walk every concatenated frame (Zstd and skippable).
- mbps
- Uncompressed throughput in MB/s (
src_len * loops / seconds) – the MEAN rate. - mbps_
best - Uncompressed throughput in MB/s from the fastest single loop.
- overlap_
size - Overlap bytes reloaded from the previous job (
overlapLog1 = none, 9 = window). - parse_
seek_ table - Parse a seek table from the end of a seekable blob.
- public_
dict_ id - Pick a public Dictionary_ID (RFC reserved ranges avoided unless
forced). - resolve_
job_ size - Job size after C’s transparent minimum (
max(512 KiB, overlap, 4*windowif unset)). - time_
loops - Run
oneat least once; keep running untilminhas elapsed (0= once). - train
- Train a zstd dictionary from
samples. Output is a trained dict C can load. - xxh64
- XXH64 with seed 0 – the only seed zstd uses for the content checksum.