Commit Graph
2317 Commits
Author SHA1 Message Date
ddidderr 845f77924a feat(cli): move separate decompression scheduling into Rust
Move the separate-destination multi-file decompression loop into the Rust
projection so Rust owns file iteration, progress counters, and aggregate
error handling. Keep destination-name construction, mirror setup, source
opening, format dispatch, diagnostics, and source removal in the C callback
boundary.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml decompression_multiple_separate -- --test-threads=1
- ulimit -v 41943040; make -B -C programs -j1 zstd
- ulimit -v 41943040; make -B -C tests -j1 test-cli-tests
2026-07-19 11:25:59 +02:00
ddidderr 802cb70184 feat(cli): move shared decompression scheduling into Rust
Move the shared-destination branch of FIO_decompressMultipleFilenames into a Rust-owned scheduler. Preserve source order, destination propagation, cursor advancement, success counting, aggregate errors, and C-owned source/format/resource behavior including --rm and output close handling.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml decompression_multiple_shared_destination -- --test-threads=1
- ulimit -v 41943040; make -B -C programs -j1 zstd
- ulimit -v 41943040; make -B -C tests -j1 test-cli-tests
2026-07-19 11:10:09 +02:00
ddidderr fbc80de7dc feat(cli): move separate-output scheduling into Rust
Move the separate-destination branch of FIO_compressMultipleFilenames into a Rust-owned scheduler. Preserve source ordering, currFileIdx advancement, successful-file counting, aggregate error handling, and post-loop collision checks while retaining destination construction and private file/resource work in C callbacks.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml compression_multiple_separate -- --test-threads=1
- ulimit -v 41943040; make -B -C programs -j1 zstd
- ulimit -v 41943040; make -B -C tests -j1 test-cli-tests
2026-07-19 10:52:31 +02:00
ddidderr 035001b769 feat(cli): move shared-destination scheduling into Rust
Move the shared-output arm of FIO_compressMultipleFilenames into a Rust
scheduler. Rust now owns input-order iteration, processed-file accounting,
index advancement, and non-short-circuiting error aggregation while C retains
file validation, private resources, callbacks, diagnostics, and destination
lifetime.

Test Plan:
- cargo +nightly fmt --manifest-path rust/Cargo.toml
- cargo test --manifest-path rust/Cargo.toml compression_multiple_shared_destination -- --test-threads=1 (2 passed)
- cargo clippy --manifest-path rust/Cargo.toml --tests -- -D warnings
- make -B -C lib -j1 lib
- make -B -C programs -j1 zstd
- make -B -C tests -j1 test-cli-tests (41 passed)
- all commands used CARGO_BUILD_JOBS=1 where applicable and
  ulimit -v 41943040; no heavyweight jobs ran concurrently

Commit is intentionally unsigned because GPG pinentry hangs in this
non-interactive environment.
2026-07-19 10:31:19 +02:00
ddidderr b048937992 feat(cli): move adaptive decisions into Rust
Move the scalar runtime --adapt predicates and compression-level normalization
into Rust. Rust now decides output blocking, output backlog, input starvation,
blocked-input speedups, and bounded slower/faster level changes through an
explicit projection.

Keep the CLI iteration order, refresh clock, frame-progression snapshots,
private FIO/ZSTD contexts, diagnostics, and ZSTD_CCtx_setParameter() mutation
in C. The new C/Rust layout assertions make the scalar policy ABI explicit
without exposing those private layouts.

Test Plan:
- focused adaptive-policy tests: 6 passed
- cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1:
  533 passed
- cargo test --manifest-path rust/cli/Cargo.toml --all-targets --
  --test-threads=1: 169 passed
- legacy compression/decompression/dictionary-builder feature matrix:
  588 passed
- six library/CLI clippy gates with -D warnings
- capped serial native library/program rebuilds, 41 CLI tests, Rust library
  smoke, and full test-zstd round trips including --adapt cases
- capped serial stress gates: 278 fuzzer cases, 84+129+143 zstream cases,
  and 1,601 decode-corpus cases
- every heavyweight command used CARGO_BUILD_JOBS=1 or make -j1 and
  ulimit -v 41943040; no worker/native process remained afterward

Commit is intentionally unsigned because GPG pinentry hangs in this
non-interactive environment.
2026-07-19 10:12:50 +02:00
ddidderr 423854541b feat(cli): move zstd compression loop into Rust
The CLI's zstd-format compression path previously kept the asynchronous
read, compressStream2, output-job, flush, accounting, adaptive-policy, and
progress loop together in fileio.c. That made the high-level stream
orchestration another large C-owned surface even though the Rust fileio
module already owned the neighboring format loops.

Move the format-independent zstd stream loop and read/output accounting into
FIO_rust_compressZstdFrame. The C adapter now projects read-pool, write-pool,
codec, and policy operations through narrow callbacks. C retains the private
ZSTD_CCtx interaction, adaptive-level policy, memory diagnostics, progress
formatting, and CLI error mapping, so no private C layout crosses into Rust.
Focused seam tests cover input/output ordering, final flush behavior, codec
error propagation, and incomplete known-size input handling.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1`
  -- 513 passed under the 40 GiB virtual-memory cap.
- `cargo test --manifest-path rust/cli/Cargo.toml --all-targets --
  --test-threads=1` -- 169 passed under the cap.
- `cargo clippy` lib/benches/tests for `rust` and `rust/cli`, with
  `-D warnings`, and nightly formatting -- passed.
- `make -B -C lib -j1 lib` and `make -B -C programs -j1 zstd` -- passed.
- Native CLI, full zstd, fuzzer, zstream, and decode-corpus targets -- passed
  serially under the cap.

GPG signing was attempted but unavailable because no pinentry process was
available; this repository's preceding commits are unsigned, so this commit
uses the explicit unsigned fallback.
2026-07-19 08:48:50 +02:00
ddidderr 7282ec4046 feat(cli): move optional decompression loops into Rust
Move gzip, xz/LZMA, and LZ4 frame I/O loops into Rust projections while
keeping zlib, liblzma, LZ4F, asynchronous pool operations, diagnostics, and
private C handles in C callbacks.  Preserve trailing-input accounting and
format-dispatch behavior, and stop faulty LZ4 callbacks from producing an
unbounded no-progress output loop while retaining the codec error value.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --lib lz4_decompress_projection_reports_errors_and_unfinished_input -- --test-threads=1 (1 passed)
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --lib -- -D warnings (passed)
- ulimit -v 41943040; make -B -C tests -j1 test-cli-tests (41 passed)
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1 (507 passed before final error-value assertion)
2026-07-19 08:20:46 +02:00
ddidderr cb438dc4f1 feat(cli): move decompression result policy into Rust
Move mixed-format decompression status mapping and successful-file finalization
into Rust. C keeps the diagnostic and private FIO context callbacks, while
Rust decides pass-through/error behavior and invokes final accounting only for
a successful decoded file.

Test Plan:
- cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1
- cargo test --manifest-path rust/cli/Cargo.toml --all-targets -- --test-threads=1
- cargo clippy --manifest-path rust/Cargo.toml --tests -- -D warnings
- make -B -C programs -j2 zstd
- make -B -C tests -j2 test-cli-tests
2026-07-18 23:46:17 +02:00
ddidderr fce8d34ffc feat(cli): move xz/lzma and lz4 codec loops into Rust
Move the xz/lzma and LZ4 file-compression orchestration into Rust projection
functions. C retains liblzma and LZ4F contexts, asynchronous pool ownership,
format-specific callbacks, sparse-output handling, and user-facing diagnostics.
The Rust leaves preserve input accounting, output enqueue order, progress
updates, finish/end handling, cleanup, and the original error-code mapping.
Focused projection tests cover success ordering and codec initialization,
header, update, finish, and end failures.

Test Plan:
- cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1
- cargo test --manifest-path rust/cli/Cargo.toml --all-targets -- --test-threads=1
- cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- make -B -C programs -j2 zstd
- make -B -C tests -j2 test-cli-tests test-zstd
- FUZZERTEST=-T5s make -B -C tests -j2 test-fuzzer
2026-07-18 23:28:53 +02:00
ddidderr 05561c7494 feat(cli): move gzip codec loop into Rust
Move the gzip member read, zlib deflate, finish, output-enqueue, progress,
and accounting loop into Rust. Keep zlib, asynchronous pool, sparse-output,
and diagnostic ownership in C through an explicit projection so optional gzip
builds preserve the existing CLI behavior and error mapping. Add focused tests
for callback ordering, partial input consumption, finish retries, accounting,
and initialization failures.

Test Plan:
- cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1
- cargo test --manifest-path rust/cli/Cargo.toml --all-targets -- --test-threads=1
- make -B -C programs -j2 zstd
- make -B -C tests -j2 test-cli-tests test-zstd
- FUZZERTEST=-T5s make -B -C tests -j2 test-fuzzer
- cargo clippy --manifest-path rust/Cargo.toml --tests -- -D warnings
2026-07-18 23:07:51 +02:00
ddidderr be7e656d8e feat(cli): move compression format dispatch into Rust
`FIO_compressFilename_internal()` still selected the zstd, gzip, xz/lzma, and
lz4 paths in a C-owned format switch and updated aggregate byte accounting
around those callbacks.  That left the mixed-format CLI dispatch loop outside
the Rust file-I/O orchestration even though the pools and decompression path
were already projected there.

Add a callback table for the codec leaves and move format selection, optional
codec status handling, post-success accounting, and progress-hook ordering to
Rust.  The existing C codec implementations, diagnostics, elapsed-time
formatting, and resource ownership remain unchanged; unsupported optional
formats return explicit statuses so the C wrapper preserves its original
EXM_THROW messages.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1` -- 473 passed.
- Native `test-cli-tests` -- all 41 passed.
- Native `test-zstd` -- passed, including async zstd/gzip/xz/lzma/lz4 round trips.
- `make -B -C programs -j2 zstd` and `make -B -C tests/fuzz -j2 all` -- passed.
2026-07-18 22:41:39 +02:00
ddidderr 139b45832e feat(cli): move mixed-format dispatch into Rust
Move file I/O's format probing, frame classification, callback dispatch, and
size accounting into Rust. C retains the codec-specific decompression,
pass-through, metadata, and private resource adapters, while Rust coordinates
mixed-format streams and maps callback outcomes back to the CLI error paths.

Test Plan:
- cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1
- cargo test --manifest-path rust/cli/Cargo.toml --all-targets -- --test-threads=1
- cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- make -B -C programs -j2 zstd
- make -B -C tests -j2 test-cli-tests
- make -B -C tests -j2 test-zstd
2026-07-18 22:09:05 +02:00
ddidderr b0488f285a feat(cli): move consecutive zstd frame dispatch into Rust
The CLI already delegated one zstd frame at a time to Rust, but the C
FIO_decompressFrames loop still owned repeated-frame dispatch. That left
concatenated zstd streams split across the language boundary and made the
Rust frame helper unable to preserve the next mixed-format header itself.

Add a Rust multi-frame adapter that repeatedly probes four buffered bytes,
uses the existing one-frame decoder, accumulates decoded output and progress,
and leaves a following non-zstd header or short trailing input untouched for
C's format dispatcher. Keep C responsible for probing the first format,
non-zstd dispatch, diagnostics, cleanup, and final file accounting. Decoder
errors still preserve the current input for FIO_zstdErrorHelp().

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --lib fileio_asyncio -- --test-threads=1` -- 20 passed
- `cargo clippy --manifest-path rust/Cargo.toml --lib -- -D warnings` -- passed
- `cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check` -- passed
- `make -B -C tests -j2 test-cli-tests` -- all 41 passed
- `git diff --cached --check` -- passed
- Full root `cargo clippy --all-targets/--benches/--tests -- -D warnings` remains blocked by the pre-existing `manual_repeat_n` warning in `rust/src/zstd_compress.rs` test code; no unrelated change was made.
2026-07-18 19:34:33 +02:00
ddidderr bf364cce1c feat(cli): move zstd frame decode loop into Rust
Move the zstd frame read/decode/write loop behind a narrow Rust ABI.  Rust
now owns decoder reset, asynchronous input/output buffer coordination, frame
progress accounting, frame-boundary handling, and status classification.  C
retains the mixed-format dispatcher, user-facing diagnostics, window-limit
help, progress formatting callback, source/destination policy, cleanup, and
metadata handling.

The bridge passes opaque decoder and I/O-pool pointers plus scalar counters and
out-parameters.  Decoder errors return before consuming the current input
buffer so the C diagnostic path can inspect it.  The Rust test seam covers
valid streaming, concatenated frame boundaries, pre-increment progress
semantics, decoder-error input preservation, and premature EOF.

Test Plan:
- cargo test --manifest-path rust/Cargo.toml --lib fileio_asyncio -- --test-threads=1
- cargo clippy --manifest-path rust/Cargo.toml --lib -- -D warnings
- cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check
- cargo test --manifest-path rust/Cargo.toml --lib -- --test-threads=1
- make -B -C tests -j2 test-cli-tests (all 41 passed)
- git diff --cached --check
2026-07-18 19:14:58 +02:00
ddidderr 1b85c430b1 feat(cli): move destination opening into Rust
FIO_openDstFile still performed destination classification, platform-specific
file creation, stdio buffering, and overwrite preparation in C, even though
source opening and removal already used Rust filesystem leaves. That made the
CLI backend's most important output safety path split across two implementations.

Add a Rust destination leaf with a small status ABI. Rust owns sentinel and
same-file classification, regular-file detection, platform binary open and
fdopen, truncation, and buffering. C keeps the user-facing diagnostics,
sparse-mode preference mutation, overwrite prompt, and existing remove-file
wrapper; it performs a second Rust open after an accepted overwrite decision so
no prompt or policy is duplicated. Existing file contents are left untouched
until that C-owned decision is complete.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --lib -- --test-threads=1`
  -- passed (411 tests, including destination classification/open tests).
- `cargo clippy --manifest-path rust/Cargo.toml --lib -- -D warnings`
  -- passed.
- `cargo clippy --manifest-path rust/cli/Cargo.toml --lib
  --no-default-features --features cli,compression,decompression,benchmark,
  dict-builder -- -D warnings` -- passed.
- Nightly fmt checks for both Rust manifests -- passed.
- `make -B -C tests -j2 test-cli-tests` -- passed (41 tests).
2026-07-18 18:44:12 +02:00
ddidderr 725c064df5 feat(cli): move benchmark orchestration into Rust
The C benchmark translation unit still contained the complete BMK
implementation, so program builds and paramgrill could silently keep using a
second C implementation even though rust/src/benchzstd.rs already provided the
same ABI. Replace that duplicate with a declaration-only shim and retain
compile-time checks for the by-value result and parameter layouts.

The standalone test tools do not link the full CLI archive. Keep their
helpers archive free of the benchmark and trace-only objects, and add a
separate benchmark archive for paramgrill so the shim remains linkable without
pulling program-only trace dependencies into datagen and similar targets.

Test Plan:
- `cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark,dict-builder --lib -- --test-threads=1` -- 165 passed
- `make -B -C programs -j2 zstd` -- passed
- `./programs/zstd -b1 tests/hello` -- passed
- `make -B -C tests paramgrill` -- passed
- `./tests/paramgrill -S tests/hello` -- passed
- `make -C tests -j2 test-fullbench` -- passed
- targeted Rust clippy and nightly rustfmt checks -- passed
- full all-target clippy remains blocked by pre-existing test-only lints in `zstd_compress.rs` and `fileio_backend.rs`
2026-07-18 18:28:31 +02:00
ddidderr 829f781855 feat(cli): move trace callbacks into Rust
The CLI trace translation unit still contained the complete CSV writer and
strong callback implementations even though the Rust CLI archive already had
the equivalent trace module. Reduce the C file to its public-header shim and
make the Rust implementation authoritative, preserving the exact CSV header,
version assertion, timing fields, and no-trace build behavior. Focused tests
cover header creation and the version-mismatch assertion.

Test Plan:
- CLI tests: 161 default and 127 reduced-feature -- passed
- Focused trace tests: 3/3 in both configurations -- passed
- `make -B -C programs -j2` for all CLI variants -- passed
- Trace compression/decompression smoke test -- passed
- C shim compile with and without `ZSTD_NOTRACE` -- passed
- Clippy, nightly rustfmt, and `git diff --check` -- passed
2026-07-18 18:00:42 +02:00
ddidderr e02cf8b052 feat(cli): move compression preference formatting into Rust
The verbose compression-preference summary was still formatted by the C
file-I/O orchestration layer even though the preference object and the rest of
its policy helpers already lived in Rust. Move the option selection and exact
summary formatting into the Rust CLI archive, keeping the public C function as
a narrow assertion-and-dispatch shim. The Rust formatter preserves the legacy
option spellings, default memory limit, integer casts, and stderr output, with
a focused string-format regression test.

Test Plan:
- `cargo fmt --manifest-path rust/cli/Cargo.toml -- --check` -- passed
- `cargo test --manifest-path rust/cli/Cargo.toml --lib fileio_prefs -- --test-threads=1` -- 46 passed
- `git diff --check` -- passed
2026-07-18 17:54:12 +02:00
ddidderr 643cb45d89 feat(cli): move dictionary release dispatch into Rust
Route FIO_freeDict through the Rust filesystem backend for malloc-backed and
mapped dictionaries. Keep enum validation in C, pair Windows views with their
file handles, support the non-POSIX malloc fallback, and clear every ownership
field so repeated cleanup remains harmless.

Test Plan:
- cargo test --manifest-path rust/cli/Cargo.toml --lib fileio_backend -- --test-threads=1 (25 passed)
- cargo clippy --manifest-path rust/cli/Cargo.toml --lib -- -D warnings
- rustfmt +nightly --edition 2021 rust/src/fileio_backend.rs --check
- make -C programs -j2 zstd
- git diff --check
2026-07-18 17:45:19 +02:00
ddidderr e557549ff4 fix(build): gate CLI dictionary builder by feature
Keep dictionary-training code out of compressor-only and decompressor-only CLI
archives, where its ZDICT symbols are intentionally absent. Add a dedicated
Rust CLI archive for zstd-dictBuilder, enable the builder feature only for the
full and dictionary-builder programs, and make reduced-feature help use the
feature-independent max-level helper.

Test Plan:
- cargo test --manifest-path rust/cli/Cargo.toml --lib -- --test-threads=1 (158 passed)
- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,dict-builder --lib -- --test-threads=1 (124 passed)
- cargo clippy --manifest-path rust/cli/Cargo.toml --lib -- -D warnings
- cargo clippy --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,dict-builder --lib -- -D warnings
- make -C programs -j2 zstd zstd-small zstd-frugal zstd-decompress zstd-compress zstd-dictBuilder
- git diff --check
2026-07-18 17:36:24 +02:00
ddidderr f7a2576761 feat(cli): move dictionary mmap lifecycle into Rust
Move the platform-specific dictionary mapping and release operations behind the
Rust CLI archive while keeping size policy, diagnostics, and FIO_Dict_t
ownership decisions in C. POSIX descriptors and Windows handles are cleaned up
on every failure path, and zero-length dictionaries use an owned sentinel so
the existing non-null dictionary invariant remains valid.

Test Plan:
- cargo test --manifest-path rust/cli/Cargo.toml --lib fileio_backend (24 passed)
- cargo clippy --manifest-path rust/cli/Cargo.toml --lib -- -D warnings
- make -C programs -j2 zstd
- --mmap-dict compression/decompression round trip with programs/README.md
- programs/zstd --mmap-dict --test on the generated frame
- rustfmt +nightly --edition 2021 rust/src/fileio_backend.rs --check
- git diff --check
2026-07-18 17:34:32 +02:00
ddidderr 5dee449036 feat(cli): move source file opening leaf to Rust
Keep FIO_openSrcFile's stdin sentinel handling, Windows binary-mode setup,
existing diagnostics, and FILE ownership in the C wrapper while moving only
non-stdin source validation and opening behind the Rust CLI ABI. The Rust leaf
returns distinct stat, non-regular, and fopen failure statuses, delegates
metadata and regular/FIFO/block-device classification to the existing utility
ABI, and passes the original C path directly to fopen("rb"). Opaque stat_t and
FILE* pointers cross the boundary, and the output stream is published only on
success; Rust never closes a returned stream.

Focused backend tests cover regular-file reads, missing and directory paths,
unchanged output pointers on failure, empty and spaced paths, and symlinks.
FIFO acceptance remains in the preserved classification order without a test
that could block while opening a named pipe.

Test Plan:
- `cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression --lib fileio_backend` -- 22 passed
- CLI clippy for library, benches, and tests with `cli,compression,decompression,benchmark`, before and after nightly formatting -- clean after the new-code warnings were fixed
- `cargo +nightly fmt --manifest-path rust/cli/Cargo.toml --all -- --check` -- passed
- Root Rust clippy with the reduced `compression` feature split for library, benches, and tests -- passed with one pre-existing warning in forbidden `rust/src/zstd_compress.rs`
- `make -B -C programs -j2 zstd` -- passed
- `make -B -C programs -j2 zstd-small zstd-frugal zstd-dictBuilder` -- passed with existing unused-function warnings in compact CLI builds
- `make -C tests -j2 test-cli-tests` -- all 41 CLI tests passed, including file-stat coverage
- `make -C tests -j2 test-zstd` -- reached dictionary training, then hit a segmentation fault in the unrelated concurrent compressor/dictionary path
- `git diff --check` and `git diff --cached --check` -- passed
2026-07-18 16:52:52 +02:00
ddidderr 17b610b73c feat(cli): move --list frame analysis to Rust
Keep the C --list orchestration, file ownership, fileInfo_t storage, and
DISPLAYLEVEL/reporting behavior in programs/fileio.c while replacing only the
frame scanner with a guarded Rust FFI leaf. The Rust implementation preserves
the C status values, fread lookahead, large-file seek/tell behavior, frame and
skippable-frame accounting, content-size and window updates, checksum capture,
RLE and invalid-block handling, dictionary-ID aggregation, and truncation
classification without taking ownership of FILE or the output structure.

A C diagnostic bridge keeps the existing CLI messages and warning formatting
outside the scanner. The Rust tests use temporary C streams and focused frame
buffers, including a test-only header API shim so the unit tests remain safe
and link independently of the full CLI binary. The decompression feature guard
also keeps the scanner absent from no-decompression CLI archives.

Test Plan:
- cargo test --no-default-features --features cli,compression,decompression,benchmark --lib fileio_prefs (45 passed)
- cargo test --no-default-features --features cli,compression,decompression,benchmark (152 passed)
- library and CLI clippy for main, benches, and tests, before and after nightly formatting (clean)
- cargo +nightly fmt -- --check for both library and CLI crates (clean)
- make -B -C programs -j2 zstd, zstd-small, zstd-frugal, and zstd-dictBuilder (passed)
- exact --list/-l playTests.sh blocks (passed)
- make -C tests -j2 test-cli-tests (41 passed)
- nm archive guard check confirmed FIO_rust_analyzeFrames only in the decompression-enabled CLI archive
- zstd-decompress remains blocked by the pre-existing DEFAULT_MAX_CLEVEL feature-gating error in rust/src/zstd_cli.rs
- zstd-compress remains blocked by pre-existing unresolved ZDICT_* references; neither blocker is in the owned files
2026-07-18 16:31:55 +02:00
ddidderr abcc066622 feat(cli): move dictionary stat leaf to Rust
Move dictionary-path statting behind the existing Rust CLI file-I/O backend while keeping FIO_getDictFileStat as the C policy adapter. The adapter still owns the NULL-path early return, errno-based EXM_THROW(31) diagnostic, EXM_THROW(32) regular-file policy, and all dictionary orchestration.

FIO_rust_getDictFileStat crosses only the existing path and stat_t boundary, delegates metadata and regular-file classification to UTIL_stat and UTIL_isRegularFileStat, and returns 0/1/2 for success, stat failure, or non-regular input. Reusing those ABIs preserves the C stat_t representation, errno behavior, and stat's symlink-following semantics. Focused backend tests cover regular, missing, directory, NULL, and symlink paths.

Test Plan:
- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression --lib fileio_backend (15 passed)
- cargo clippy --no-default-features --features compression, including --benches and --tests (passed)
- CLI cargo clippy with cli,compression,decompression,benchmark, including --benches and --tests (passed)
- cargo +nightly fmt checks for the owned Rust module and CLI crate (passed); root-wide check remains limited by unrelated dict_builder_zdict.rs edits
- Existing CLI dictionary scenarios for missing and directory paths retained status 31/32 and exact diagnostics
- git diff --check and git diff --cached --check (passed)
- zstd build variants were attempted; full links remain blocked by unrelated active dict-builder/zstd-cli/archive edits after the owned C file compiled
2026-07-18 15:52:15 +02:00
ddidderr 23450d8c3b feat(cli): move patch-from parameter policy to Rust
Keep the public ZSTD_getCParams() selection and all DISPLAYLEVEL output in
programs/fileio.c, but pass its by-value compression-parameter snapshot to a
Rust policy leaf. Rust now preserves the original source-size highbit and
window clamping rules, validates and updates the patch memory limit before
success outputs, derives cycleLog, updates comprParams->windowLog, and applies
automatic LDM without overwriting the explicit-LDM diagnostic semantics.

The Rust ABI returns the raw file window and the two diagnostic predicates so
C can retain its existing messages and optimal-parser note ordering. C layout
assertions cover the seven-word compression-parameter snapshot on both
platform-width variants; rejected unknown and oversized inputs leave all
outputs unchanged.

Test Plan:
- Rust clippy pre/post nightly-format matrix for library compression and CLI
  cli,compression,decompression,benchmark features -- passed.
- `cargo test --manifest-path rust/cli/Cargo.toml --no-default-features
  --features cli,compression,decompression,benchmark` -- 137 passed.
- `make -C programs -j2 zstd` -- passed.
- `make -C tests -j2 test-cli-tests` -- 41 passed.
- `python3 tests/cli-tests/run.py decompression/pass-through.sh` -- passed.
- Focused patch-from round trips, stream-size failure ordering, and automatic
  long-mode diagnostics -- passed.
- `make -C tests -j2 test-rust-lib-smoke` -- passed.
- No i686 Rust target is installed; 32-bit policy bounds are covered by
  size_of-based constants and C/Rust ABI assertions.
2026-07-18 15:29:02 +02:00
ddidderr a9b11394ce feat(cli): move patch-from window policy to Rust
Keep patch-from orchestration in C while extracting only the bounded window
selection and automatic-LDM decision into the Rust CLI leaf. The C caller
still computes the raw file window with FIO_highbit64, obtains cParams,
updates the memory limit, emits warnings and optimal-parser notes, and writes
comprParams->windowLog and prefs->ldmFlag. Rust receives only scalar policy
inputs and two output pointers, clamps the selected window to the target's
10..30/31 bounds, and compares the unclamped value strictly against cycleLog.
This preserves equality as no-LDM and keeps values above the maximum eligible
to trigger LDM. Focused unit tests cover both clamps and each comparison edge.

Test Plan:
- `cargo clippy --manifest-path rust/Cargo.toml --no-default-features
  --features compression` with library, `--benches`, and `--tests`, before and
  after formatting -- passed
- `cargo +nightly fmt --manifest-path rust/Cargo.toml --
  --config skip_children=true` and nightly rustfmt on the owned file -- passed
- `cargo test --manifest-path rust/cli/Cargo.toml --no-default-features
  --features cli,compression,decompression,benchmark fileio_prefs` -- 36 passed
- `make -C programs -j2 zstd` -- passed
- `make -C tests -j2 test-cli-tests` -- 41 passed
- Focused patch-from round trip and automatic long-mode trigger -- passed
2026-07-18 15:19:30 +02:00
ddidderr 8ade3da099 feat(programs): move pass-through copying into Rust
Keep decompression resource ownership and file orchestration in C while the
Rust AIO module handles the pass-through byte-copy leaf through a two-pool ABI.
The Rust implementation derives the block limit from the actual read and write
job buffers, preventing a write-job overrun when their configured sizes differ.
It preserves the existing enqueue/reacquire, consume/refill, EOF, release, and
sparse-write ordering, with pool-backed coverage for synchronous and threaded
operation.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression --lib fileio_asyncio` -- passed, 9 tests.
- Required clippy/fmt sequence against `rust/Cargo.toml` with compression -- passed before and after nightly fmt.
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression --lib` -- passed, 342 tests.
- `make -C programs -j2 zstd` -- passed.
- Manual 200 KiB and empty-input `programs/zstd -dc --pass-through` comparisons -- passed.
2026-07-18 14:53:44 +02:00
ddidderr 684963c1a9 feat(cli): move multi-file output policy to Rust
Port the scalar decision matrix for multi-input concatenation behind the CLI Rust ABI. C retains warnings, preference mutation, fatal diagnostics, and confirmation prompts; Rust now classifies protection, remove-file disabling, quiet abort, and confirmation paths with focused coverage.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml fileio_prefs::tests::multi_files_concat

- cargo clippy --manifest-path rust/cli/Cargo.toml

- cargo clippy --manifest-path rust/cli/Cargo.toml --benches

- cargo clippy --manifest-path rust/cli/Cargo.toml --tests

- cargo +nightly fmt --manifest-path rust/Cargo.toml --all

- make -B -C programs -j2 zstd

- make -C tests -j2 test-cli-tests
2026-07-18 06:38:24 +02:00
ddidderr 3599d223f9 feat(cli): move dictionary loading backend to Rust
Move malloc-backed dictionary file reads into the Rust CLI backend while keeping C responsible for stat metadata, patch-mode size policy, diagnostics, buffer-type selection, and eventual free(). The Rust leaf returns explicit open, size, allocation, and read statuses and publishes only fully read libc allocations.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml (126 tests)

- cargo clippy --manifest-path rust/cli/Cargo.toml

- make -B -C programs -j2 zstd

- make -C tests -j2 test-cli-tests (41 tests)
2026-07-18 06:02:22 +02:00
ddidderr 52c0eb4b9b feat(cli): move regular-file removal to Rust
Route the CLI backend's safe file-removal leaf through a narrow Rust status ABI while preserving C diagnostics, Windows read-only handling, and the existing return convention.

Test Plan: cargo test --manifest-path rust/cli/Cargo.toml; cargo clippy --manifest-path rust/cli/Cargo.toml; cargo clippy --manifest-path rust/cli/Cargo.toml --benches; cargo clippy --manifest-path rust/cli/Cargo.toml --tests; make -B -C programs -j2 zstd; make -C tests -j2 test-cli-tests (41 tests); make -B -C programs -j2 zstd-small zstd-frugal.
2026-07-18 05:39:21 +02:00
ddidderr ce992fb0be feat(cli): move cycle log policy to Rust
Move the CLI's strategy-dependent cycle-log calculation behind a scalar Rust ABI shim while retaining the C assertion and call-site behavior.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark (116 tests)

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets with the full CLI feature set

- make -B -C programs -j2 zstd zstd-small zstd-frugal

- make -C tests -j2 test-cli-tests (41 scenarios)
2026-07-18 05:06:48 +02:00
ddidderr 52deffe66c feat(cli): move patch memory-limit policy to Rust
Move patch-from memory-limit sizing and rejection status selection behind a Rust ABI shim. Keep the C diagnostics and assertion in place, and leave the existing preference unchanged when input sizes are unknown or exceed the window limit.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark (113 tests)

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets with the CLI feature set

- make -B -C programs -j2 zstd zstd-small zstd-frugal

- make -C tests -j2 test-cli-tests (41 scenarios) and make -B -C tests -j2 test-zstream
2026-07-18 04:54:28 +02:00
ddidderr 49f03de3e2 feat(cli): move summary display predicates to Rust
Port the single-file and multiple-file summary decisions through the existing FIO context ABI, including the display-level lookup and the original multiple-file assertion invariant. Keep the C wrappers and call sites unchanged.

Test Plan: cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark (108 passed); CLI all-target clippy; make -B -C programs -j2 zstd zstd-small zstd-frugal; make -C tests -j2 test-cli-tests (41 passed).
2026-07-18 04:43:53 +02:00
ddidderr 5362112c9c feat(cli): move file info aggregation to Rust
Mirror fileio.c's private fileInfo_t with a checked repr(C) ABI and aggregate totals, flags, and file counts through an output-pointer shim. Preserve zeroed non-aggregate fields and use wrapping arithmetic for the original integer operations.

Test Plan: cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark (106 passed); cargo clippy --all-targets with the same features; make -B -C programs -j2 zstd zstd-small zstd-frugal; make -C tests -j2 test-cli-tests (41 passed).
2026-07-18 04:31:43 +02:00
ddidderr 42481fb366 feat(cli): move decompressed filename policy to Rust
Port destination-name derivation to the Rust file-I/O preference module. Preserve build-configured suffix matching, tar-name conversion, stdin/stdout sentinels, output-directory handling, diagnostics, static-buffer reuse, and allocation behavior through the existing C adapter.

Test Plan:\n- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark\n- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features helpers\n- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression,benchmark\n- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features helpers\n- make -B -C programs -j2 zstd zstd-small zstd-frugal\n- make -C tests -j2 test-cli-tests
2026-07-18 04:14:40 +02:00
ddidderr af2991ea40 feat(cli): move compressed filename helper to Rust
Port the compressed destination-name helper to the Rust file-I/O preference module. Preserve stdin/stdout sentinels, output-directory basename handling, suffix assembly, static-buffer reuse, and allocation failure behavior behind the existing C shim.

Test Plan:\n- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark\n- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features helpers\n- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression,benchmark\n- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features helpers\n- make -B -C programs -j2 zstd zstd-small zstd-frugal\n- make -B -C tests -j2 test-cli-tests
2026-07-18 04:06:02 +02:00
ddidderr 309e227731 feat(fileio): move buffer helpers to Rust
Route file-I/O input/output buffer construction and the LZ4 block-size mapping through Rust ABI leaves while preserving the existing C helper names and public buffer layouts. Add layout, field, and formula coverage.

Test Plan: cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark; cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression,benchmark; make -B -C programs -j2 zstd zstd-small zstd-frugal; make -B -C tests -j2 test-cli-tests
2026-07-18 03:54:20 +02:00
ddidderr 386ec3d0a7 feat(fileio): move size helpers to Rust
Move the file-stat size scan and highest-bit helper behind Rust ABI implementations while preserving the C file-I/O surface and unknown-size sentinel behavior. Add temporary-file and boundary coverage for the migrated helpers.

Test Plan: cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark; cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features helpers; cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression,benchmark; cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features helpers; make -B -C programs -j2 zstd zstd-small zstd-frugal; make -B -C tests -j2 test-cli-tests
2026-07-18 03:39:22 +02:00
ddidderr 65bfc6bb2b feat(fileio): move filename collision checks to Rust
Implement basename extraction, bytewise sorting, collision reporting, and allocation failure handling in the Rust fileio preferences module. Keep programs/fileio.c as the stable ABI shim and preserve non-UTF-8 filenames without lossy conversion.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression

- make -B -C tests -j2 test-cli-tests

- git diff --cached --check
2026-07-18 03:19:57 +02:00
ddidderr 96c7f3b900 feat(cli): move benchmark bridge into Rust
Move benchmark parameter normalization and dispatch into the Rust CLI archive while retaining the stable C launcher entry point. Keep compact CLI variants benchmark-free and add an explicit helpers feature for the C test generators.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features benchmark

- cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features helpers

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression,benchmark

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features helpers

- make -B -C programs -j2 zstd zstd-small zstd-frugal

- make -B -C tests -j2 test-cli-tests

- programs/zstd -b1i1 -q
2026-07-18 03:18:58 +02:00
ddidderr 4171c42448 feat(fileio): move output path construction to Rust
Move the basename-preserving output-directory helper behind the existing Rust utility ABI. Keep the libc allocation contract and platform separator behavior intact while leaving the C file-I/O engines and higher-level naming policy unchanged.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml (93 passed)

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets

- make -B -C tests -j2 test-cli-tests (41 passed)
2026-07-18 02:52:26 +02:00
ddidderr 9f85a7ebd7 feat(cli): move trace callbacks into Rust
Implement the CLI trace callbacks and CSV logger in Rust, preserving the ZSTD_Trace ABI, timing fields, parameter reporting, mutex-protected writes, and no-op disabled behavior. Add the module to every Rust CLI archive and exclude the duplicate C trace object from Rust-backed program targets.

Test Plan:

- cargo test --manifest-path rust/cli/Cargo.toml (92 passed)

- cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets

- make -B -C programs -j2 zstd

- Rust trace smoke: programs/zstd -q --trace=/tmp/zstd-rust-trace-smoke.csv -c /tmp/levels-input

- make -B -C tests -j2 test-cli-tests (41 passed)
2026-07-18 02:50:25 +02:00
ddidderr 96a0eabdb9 feat(bench): port benchzstd orchestration to Rust
Replace the program archive's C benchmark orchestration with the complete
Rust port while retaining the public benchzstd.h ABI and result/error
contracts. Include the module only in full CLI archives and remove only
benchzstd.c from the program source set, leaving C test targets on their
existing implementation.

Test Plan:
- cargo test --manifest-path /tmp/zstd-benchzstd.IHWpLD/Cargo.toml (6 passed)
- cargo check and cargo clippy --all-targets in the focused harness (passed)
- standalone release archive build and BMK_* symbol inspection (passed)
- make -C programs zstd (passed before concurrent CLI edits)
- make -C tests -B paramgrill (passed)
- native synthetic, multi-file, dictionary, and invalid-frame benchmark smoke tests (passed)
2026-07-18 01:47:33 +02:00
ddidderr b6611f9f90 feat(fileio): port async pools to Rust
Replace programs/fileio_asyncio.c with a declaration-only shim and register
Rust's async file-I/O implementation in the library archive. Preserve the C
ABI for pool and job contexts, including DEBUGLEVEL pointer-based pthread
wrappers, and select separate Rust build configurations for those layouts.
Keep ordered-read queue state locked while waiting, drain queued work before
shutdown frees job buffers, and use platform large-file seeks for sparse writes.

Test Plan:
- `cargo test --no-default-features --lib fileio_asyncio` (7 passed).
- `cargo test --no-default-features --features debug-pthread --lib fileio_asyncio` (7 passed).
- `cargo check --all-targets`, clippy library/benches/tests, and nightly fmt check (passed).
- Threaded program build and README round-trip (passed).
- `make -C tests poolTests` and `./tests/poolTests` (passed).
- Current C shim object defines no `AIO_*` symbols; the Rust archive exports all 20 declarations.
- Full standalone all-target Rust tests and the default CLI archive rebuild remain affected by unrelated C/Rust integration and another worker's in-progress benchmark changes.
2026-07-18 01:43:25 +02:00
ddidderr 3fa5872848 feat(cli): port benchmark and compatibility option handling
Restore benchmark decode mode, auto-thread selection, alternate frame formats,
gzip/xz/lzma/lz4 aliases, and trace lifecycle handling in the Rust frontend.

Test Plan:
- RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo test --manifest-path rust/cli/Cargo.toml
- RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- make -B -C programs zstd V=1
- make -C tests check V=1
2026-07-12 18:08:09 +02:00
ddidderr cd7ae43da7 feat(cli): port utility and dictionary I/O helpers to Rust
Move filename tables, file-list expansion, core-count helpers, statistics,
and dictionary sample loading behind Rust implementations while retaining
the narrow C ABI used by the CLI.

Test Plan:
- RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo test --manifest-path rust/cli/Cargo.toml
- RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- make -B -C programs zstd V=1
- make -C tests check V=1
2026-07-12 18:06:51 +02:00
ddidderr 60877175a4 feat(cli): port file I/O preferences to Rust
Move fileio preference and context allocation, defaults, setters, and small
query helpers into Rust while keeping the actual file operations in C. Keep
the C structs and ABI declarations as anchors, and make the CLI build track
the new Rust source.

Test Plan:
- rustfmt +nightly --check --edition 2021 rust/src/fileio_prefs.rs rust/cli/src/lib.rs
- RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo test --manifest-path rust/cli/Cargo.toml
- RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- git diff --cached --check
2026-07-12 10:39:35 +02:00
ddidderr ecf03ce020 build(rust): link Rust CLI generators into program tests
Keep the original C translation units as declaration-only build shims while
the Rust CLI helper archive owns datagen and lorem. Track both Rust sources in
the program and test archive prerequisites, and link the helpers-only archive
into C test binaries that still provide their own file I/O and orchestration.
This preserves the existing C test harnesses while making the migrated helper
implementations the single definitions used by the binary and tests.

Test Plan:
- make -C programs zstd V=1
- make -C tests datagen V=1
- make -C tests test-rust-lib-smoke V=1
- git diff --check

Refs: programs/datagen.c, programs/lorem.c, tests/Makefile
2026-07-12 09:19:15 +02:00
ddidderr bdd35c838d build(rust): add legacy feature scaffolding
The legacy decoders (lib/legacy/zstd_v01.c .. zstd_v07.c) are next in
the Rust migration. Each of those files is a frozen snapshot of the
FSE/Huff0 entropy coders and frame logic of one historical release, so
their ports must not reuse the modern Rust entropy modules and must not
share code with each other: outputs and error codes have to stay
byte-identical to the frozen C forever. This commit installs the
build-system scaffolding so seven per-version ports can land
independently, each adding only its own module file plus a one-line
registration in rust/src/legacy/mod.rs.

Cargo grows features legacy-v01 .. legacy-v07. They are never default
features: the C build defaults differ per build system, so each build
system passes the list explicitly, derived from its own legacy
configuration:

- lib/Makefile and programs/Makefile map ZSTD_LEGACY_SUPPORT=N to the
  features for versions N..7 (0 disables legacy), mirroring the
  ZSTD_LEGACY_FILES selection in lib/libzstd.mk.
- tests/Makefile always enables all seven features because its
  ZSTDLEGACY_FILES wildcard compiles every lib/legacy/*.c regardless of
  the dispatch level.
- build/meson maps legacy_level exactly like the makefiles; build/cmake
  enables all seven whenever ZSTD_LEGACY_SUPPORT is ON because it
  always compiles all seven C files (ZSTD_LEGACY_LEVEL only selects the
  C dispatch).

Every build system also encodes the legacy selection in the Rust target
directory name (e.g. c1-d1-default-legacy5), for the same reason the
HUF mode is encoded there: a cached archive built for one configuration
must never be linked into a build expecting another. In tests/Makefile
the legacy level additionally flows into the existing HUF C-mode stamp,
so the flat C test objects (which bake -DZSTD_LEGACY_SUPPORT into the
dispatch) are rebuilt whenever the level changes. In programs/Makefile
the compress-only, decompress-only, and CLI archives keep
level-independent directories (RUST_HUF_MODE) because they are only
linked into ZSTD_LEGACY_SUPPORT=0 program variants and carry no legacy
features.

A feature whose version has not been ported yet gates nothing: the
module registration in rust/src/legacy/mod.rs is added by each port,
so enabling e.g. legacy-v05 today simply leaves that decoder in C.
This is what makes mixed C/Rust legacy levels link cleanly while the
seven ports land in any order.

Test plan:
- cd rust && cargo fmt --check && cargo clippy --all-targets
  -- -D warnings && cargo test --all-targets
- cargo clippy with --no-default-features --features
  decompression,legacy-v01 and with all seven legacy features
- make -C tests fuzzer && ./tests/fuzzer -i1 --no-big-tests
- make -C tests test-rust-lib-smoke; make -C tests test-legacy
- make -C lib libzstd.a with ZSTD_LEGACY_SUPPORT=0, 1 and default (5)
- cmake configure and meson setup (including -Dlegacy_level=1) emit the
  expected --features lists and legacy-suffixed target directories
2026-07-11 23:07:55 +02:00
ddidderr fef5f4478a feat(rust): port benchmark loop and CLI bench mode
Move the implementation of programs/benchfn.c into rust/src/benchfn.rs and
wire benchmark mode (-b/-e/-i) into the Rust CLI frontend, which previously
rejected those options as not yet implemented. `zstd -b1 -i0 FILE` and range
runs like `zstd -b5e6 -i0 FILE` work again, including the synthetic-sample
benchmark when no file is given.

benchfn.rs is a faithful port of the run/timing state machine:
BMK_benchFunction keeps the exact loop accounting (first-loop blockResults
and errorFn checks, dstSize summed on the first loop only, 0xE5 warm-up of
result buffers, nbLoops minimum of 1) and BMK_benchTimedFn keeps the same
convergence behavior (x10 workload growth for short runs, budget-based
nbLoops estimation, runs below half the run budget re-tried rather than
reported, best qualifying run returned). Arithmetic that C leaves to
unsigned wrap-around uses wrapping operations so debug builds cannot panic
where release C would wrap.

ABI notes: BMK_runTime_t and BMK_runOutcome_t are returned by value across
the C boundary and BMK_benchParams_t is passed by value, so all three are
repr(C) mirrors of benchfn.h; their field offsets are pinned by const
asserts in Rust and matching C static asserts in the benchfn.c shim, which
is now declaration-only. BMK_timedFnState_t stays opaque, fits the 64-byte
BMK_timedFnState_shell (compile-time checked), and is malloc/free-managed
so creation and destruction remain interchangeable with C callers.

The CLI parses -b (bench mode), -e (range end, digits attach directly,
defaulting to 0 like readU32FromChar) and -i (duration in seconds), then
dispatches through a new ZSTD_rust_cli_bench bridge in the zstdcli.c shim.
The bridge exists because benchmark availability is a C preprocessor
property (ZSTD_NOBENCH): orchestration and reporting stay in C benchzstd.c,
stripped variants (zstd-small, zstd-compress, zstd-decompress) compile the
stub branch and report "benchmark mode is not available in this build", and
the Rust side never references benchmark symbols directly. Level clamping
against ZSTD_maxCLevel() happens in the bridge, where the symbol is
guaranteed to exist whenever benchmarking is compiled in. -T selects the
worker count, defaulting to single-threaded like the C bench path; -S
(separate files) and --priority=rt remain unimplemented.

Makefile updates only extend the Rust source prerequisite lists with
benchfn.rs; the helpers-archive plumbing from the timefn commit already
links fullbench(-lib/-dll/32) and paramgrill, the benchfn consumers among
the C tests. Original C test sources are untouched.

Known pre-existing issues, unchanged by this commit: tests/fullbench-lib
fails to link at the base commit too (libzstd.a precedes fullbench.c in its
link line), and the cli-tests basic/help.sh, compression/levels.sh,
compression/golden.sh, and decompression/pass-through.sh scripts fail
identically with a base-commit binary because the Rust CLI frontend is
still a partial reimplementation.

Test Plan:
- cd rust && cargo fmt --check && cargo clippy --all-targets -- -D warnings
  && cargo test --all-targets && cargo build --release
- cd rust/cli && cargo fmt --check && cargo clippy --all-targets -- -D
  warnings && cargo test --all-targets; repeat tests with
  --no-default-features plus features compression / decompression / (none)
- make -C programs zstd; ./programs/zstd -b1 -i0 lib/common/xxhash.c;
  ./programs/zstd -b5e6 -i0 programs/fileio.c; ./programs/zstd -b1 -i0
  (synthetic); echo roundtrip via zstd | zstd -d
- make -C programs zstd-small zstd-compress zstd-decompress zstd-nolegacy
  zstd-dictBuilder; zstd-small -b reports benchmark unavailable; compress/
  decompress roundtrip across the split binaries
- make -C tests fullbench fuzzer zstreamtest paramgrill decodecorpus
  poolTests fullbench32 fuzzer32; ./tests/fullbench -i0 (exercises Rust
  BMK_benchTimedFn from C); ./tests/fullbench32 -i0; ./tests/fuzzer -i1
  --no-big-tests; ./tests/poolTests; make -C tests test-rust-lib-smoke
- cli-tests subset: basic/version.sh, compression/basic.sh,
  compression/multiple-files.sh pass; failing scripts match the base commit

Refs: rust/README.md
2026-07-11 14:26:21 +02:00