structured-zstd 0.0.53

Pure-Rust Zstandard (zstd) compression and decompression: all levels, streaming, dictionaries, no_std and WebAssembly ready — no FFI, no cmake
Documentation
[package]
name = "structured-zstd"
version = "0.0.53"
rust-version = "1.92"
authors = [
    "Moritz Borcherding <moritz.borcherding@web.de>",
    "Dmitry Prudnikov <mail@polaz.com>",
]
edition = "2024"
license = "Apache-2.0"
homepage = "https://structured-world.github.io/structured-zstd/dev/bench/"
repository = "https://github.com/structured-world/structured-zstd"
description = "Pure-Rust Zstandard (zstd) compression and decompression: all levels, streaming, dictionaries, no_std and WebAssembly ready — no FFI, no cmake"
exclude = ["fuzz_decodecorpus/*", "decodecorpus_files/*", "dict_tests/files/**"]
# Package metadata points at a crate-local symlink so the packaged crate and repo root README stay in sync.
readme = "README.md"
keywords = ["zstd", "zstandard", "decompression", "compression", "no-std"]
categories = ["compression", "no-std", "wasm", "encoding"]
# The C-binding benches, conformance tests, and FFI diagnostic examples live in
# the non-published `ffi-bench` crate so this library never depends on the C
# `zstd` bindings. Auto-discovery is disabled because those source files still
# physically live under `benches/`, `tests/`, and `examples/` here and are
# compiled as targets of `ffi-bench` via explicit `path` entries.
#
# Consequence for new tests: `tests/` auto-discovery is OFF, so a pure-Rust
# integration test dropped into `zstd/tests/` would NOT run under
# `cargo test -p structured-zstd`. Add pure-Rust tests as unit tests under
# `src/` (the `#[cfg(test)] mod tests` tree, which always runs) or, if a
# `tests/`-style integration file is required, register it with an explicit
# `[[test]]` entry here. C-binding tests always go to `ffi-bench`.
autobenches = false
autotests = false
autoexamples = false

# The command-line tool ships from this crate rather than a second package, so
# `cargo add structured-zstd` and `cargo install structured-zstd` name the same
# thing. It carries no dependencies of its own — argument parsing, progress
# display and its error type are written against `std` — so `required-features`
# names only library capabilities, all of which are in `default`. That is what
# makes `cargo install structured-zstd` work with no flags while a library
# consumer's dependency graph stays untouched: a `no_std` build simply does not
# select this target.
#
# The list is what the parser ADVERTISES, not the minimum that links: `-t` must
# actually verify checksums (which needs `hash`, pulled in by `ldm`) and
# `--long` must actually do long-distance matching, or a custom
# `--no-default-features` install would answer `OK` for a frame whose checksum
# is corrupt. A tool that reports success without doing the check is worse than
# one that refuses to build.
#
# Deliberately NOT named `zstd`: `cargo install` writes into a directory that
# usually precedes `/usr/bin` on `PATH`, so that name would shadow the system
# tool for everyone who installs this. It dispatches on `argv[0]`, so an
# alternatives entry or a `unzstd` / `zstdcat` symlink still selects the
# matching default mode.
[[bin]]
name = "structured-zstd"
path = "src/bin/structured-zstd/main.rs"
required-features = ["std", "dict-builder", "ldm"]

# docs.rs builds the crate with the public feature set so feature-gated
# items (e.g. the `dictionary` module behind `dict-builder`) appear in the
# published documentation. We list the public features explicitly rather
# than using `all-features = true` because the manifest also exposes
# `rustc-dep-of-std` (libstd-build-only — swaps in `rustc-std-workspace-*`
# crates), `bench-internals` (widens the API surface for benches), and
# `fuzz-exports` (widens it for fuzz targets); none of these should appear
# on docs.rs. The `--cfg docsrs` flag activates the
# `#[cfg_attr(docsrs, doc(cfg(...)))]` annotations that render feature
# badges on each item.
[package.metadata.docs.rs]
features = ["std", "hash", "ldm", "dict-builder", "lsm"]
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
# Locked behind the `hash` feature flag
twox-hash = { version = "2.0", default-features = false, features = ["xxhash64"], optional = true }
fastrand = {version = "2.3.0", optional = true }
# Optional sync primitive for the FSE default-table cache on no-atomic
# targets (Cortex-M0/M0+, AVR, MSP430 — anywhere `target_has_atomic =
# "ptr"` is false). When this feature is enabled the cache uses a
# critical-section-protected `static mut` slot; when disabled the
# no-atomic build skips the cache entirely and returns an owned
# `Box<FSETable>` per call, dropped with the owning `FrameCompressor`
# (no leak — same memory shape as the pre-cache status quo on those
# targets). On targets with atomic pointer support (every modern
# desktop / server / mobile / Cortex-M3+ / RISC-V-A target) the dep
# is dead code and never instantiated — those targets use the lock-
# free `AtomicPtr` path unconditionally.
critical-section = { version = "1.2", optional = true }

# Internal feature, only used when building as part of libstd, not part of the
# stable interface of this crate.
compiler_builtins = { version = "0.1.2", optional = true }
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }


[dev-dependencies]
# This library imports zero C bindings. The `zstd` (libzstd) cross-checks,
# the criterion benches, the `dhat` profiling examples, and the FFI parity
# tests all live in the sibling `ffi-bench` crate, which depends on both this
# crate and `zstd`. Only the pure-Rust unit/integration tests run here.
rand = "0.10"

[features]
default = [
    "hash",
    "ldm",
    "std",
    "kernel-scalar",
    "kernel-sse",
    "kernel-bmi2",
    "kernel-avx2",
    # `kernel-vbmi2` (AVX-512) is intentionally OFF by default: on AVX-512
    # hosts the runtime dispatch otherwise selects the VBMI2 decode tier, which
    # the dashboard's AVX-512 runner measured far SLOWER than the AVX2 tier
    # (AVX-512 license-based frequency downclocking stalls the whole decode,
    # and the bursty/memory-bound decode never amortizes the heavier kernel).
    # With it off, AVX-512 hosts fall back to the AVX2 tier (faster there). The
    # kernel is kept and can be opted in via `--features kernel-vbmi2` for a
    # sustained-AVX-512 workload that genuinely benefits.
    "kernel-neon",
    "kernel-sve",
    "kernel-simd128",
    # Present in `default` so the bundled command-line tool, whose `--train`
    # needs it, builds from a plain `cargo install structured-zstd`. It adds
    # one small dependency (`fastrand`) and no transitive ones; a build that
    # does not want it turns default features off, as `no_std` builds already
    # do.
    "dict-builder",
]
# Per-CPU-tier kernel selection, covering the decoder and the encoder. The
# default build enables every kernel except `kernel-vbmi2`; with `std`,
# `detect_cpu_kernel()` (decode) and `fastpath::select_kernel()` (encode) pick
# the best tier at runtime — a universal binary that adapts to any CPU. On
# `no_std` the tier is fixed at compile time from `target_feature`, baking
# the chosen ISA into the build; on wasm it is always compile-time, since the
# kernels there additionally require `target_feature = "simd128"`.
# Constrained targets can trim the SIMD trampolines + their
# dispatch arms by disabling the tiers they don't need; the scalar kernel
# is always compiled as the fallback, so the lowest enabled tier always has
# a backstop. Each feature only affects builds for its architecture (a
# `kernel-avx2` flag is inert on aarch64, `kernel-neon` inert on x86), so
# the all-on default is safe everywhere. `kernel-vbmi2` and `kernel-sve` are
# decoder-only: the encoder has no AVX-512 or SVE tier. `kernel-sse` covers
# two encoder tiers, SSE4.2 and a plain-SSE2 fallback for CPUs without it.
# The implication chain mirrors the
# real ISA dependency: AVX2 implies BMI2 implies SSE2; SVE implies NEON.
# `kernel-scalar` is a marker only: the scalar kernel is compiled
# unconditionally (it is the mandatory fallback), so this flag gates no code.
# It exists so the scalar tier can be named explicitly in a feature set; a
# scalar-only build is equivalently `--no-default-features` (no SIMD tier
# enabled) or `--no-default-features --features kernel-scalar`.
kernel-scalar = []
kernel-sse = []
kernel-bmi2 = ["kernel-sse"]
kernel-avx2 = ["kernel-bmi2"]
kernel-vbmi2 = ["kernel-avx2"]
kernel-neon = []
kernel-sve = ["kernel-neon"]
# WebAssembly fixed-128-bit SIMD tier (`simd128`). Inert on non-wasm targets
# the same way `kernel-neon` is inert on x86. wasm has no runtime CPU
# detection, so the tier is chosen at compile time from `target_feature =
# "simd128"`; consumers build with `-C target-feature=+simd128`. Covers the
# two 128-bit-class kernels that port directly (row tag-scan, match-copy);
# the 256-bit (AVX2/VBMI2) and scalar-bit-manip (BMI2) kernels have no
# simd128 equivalent and stay scalar on wasm.
kernel-simd128 = []
dict-builder = ["std", "dep:fastrand"]
hash = ["dep:twox-hash"]
# Long-distance matching in the encoder. Implies `hash`: the LDM match finder
# hashes each `min_match_length` window with XXH64. Without it the parameter
# builder still accepts `enable_long_distance_matching(true)` and the frame
# stays valid, but no long-distance matches are produced.
#
# Not to be confused with `lsm` below (storage-format extensions) — the names
# differ by one letter and mean unrelated things.
ldm = ["hash"]
# Opt-in cache for FSE default tables on no-atomic targets. See
# `fse_encoder::default_*_table` for the implementation split. On
# targets with atomic pointer support this feature is a no-op.
critical-section = ["dep:critical-section"]
std = []

# ---------------------------------------------------------------------------
# Internal features. NOT part of the public API: they widen the crate's
# surface or add diagnostics for this repository's own benches, fuzz targets
# and examples. They carry no stability guarantee and can change or disappear
# in any release, so downstream crates should not enable them. Excluded from
# the docs.rs feature set above for the same reason.
# ---------------------------------------------------------------------------

# Widens the API surface so the benches in `ffi-bench` can reach internals.
# CI enforces that the parity benches do NOT enable it, since the wider
# surface would bias a Rust-vs-C comparison.
bench-internals = []
# Widens the API surface for the fuzz targets.
fuzz-exports = []
# Diagnostic-only: atomic histograms of the match/literal copy shape on the
# decode path (call counts + size buckets + requested-vs-overshoot byte
# totals). Off in every shipping / bench build (zero codegen impact). Enabled
# by the `copy_shape` example to capture the copy-call distribution, which is
# deterministic from the compressed input and therefore architecture-
# independent (only the per-call timing is CPU-tier specific).
copy-shape-stats = ["std"]
# Diagnostic tracing of the Fast kernel's inner loop — per-iteration state
# dumps gated at compile time so production builds carry zero cost. Runtime
# activation via `STRUCTURED_ZSTD_KERNEL_TRACE=1` env var. Used by the
# `trace_fast_kernel` example for #220 ratio-divergence investigation.
kernel-trace = ["std"]
# Opt-in storage-format extensions: typed Rust APIs that downstream
# storage / wire-format consumers (lsm-tree, future graph stores) can
# layer on top of the spec-mandated zstd decoder behaviour. Default
# off, no C FFI symbols added regardless of this feature's state.
# Currently exposes:
# - expected-field validation setters on `FrameDecoder`
#   (`expect_dict_id` / `expect_window_descriptor`) for wire-format
#   consumers that need post-AEAD-decrypt sanity checks against a
#   pinned `dict_id` / `window_descriptor`.
# - typed `SkippableFrame` builder + `write_skippable_frame` free
#   function in `zstd::skippable` for RFC 8878 §3.1 skippable
#   frames (16-variant magic + 4-byte LE length + payload).
# Other typed APIs land here over time as bilateral storage-format
# work expands the surface.
lsm = []

# Internal feature, only used when building as part of libstd, not part of the
# stable interface of this crate.
rustc-dep-of-std = ["dep:compiler_builtins", "dep:core", "dep:alloc"]

# All benches, integration tests, and FFI diagnostic examples are targets of
# the non-published `ffi-bench` crate (they link the C `zstd` bindings); their
# source files remain under `benches/`, `tests/`, and `examples/` here and are
# referenced from `../ffi-bench/Cargo.toml` via `path`.