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
This commit is contained in:
+42
-5
@@ -57,6 +57,9 @@ zstd ABI:
|
||||
- `pool` implements the bounded worker pool used by multithreaded compression.
|
||||
- Dictionary support
|
||||
- `zstd_ddict` owns, loads, copies, and references decode dictionaries.
|
||||
- Legacy decoding
|
||||
- `legacy` hosts one frozen module per historical format (v0.1 through
|
||||
v0.7). No version has been ported yet; all decoders are still C.
|
||||
- Block decompression
|
||||
- `zstd_decompress_block` decodes literal and sequence sections, maintains
|
||||
FSE/Huffman repeat state, and executes compressed-block sequences.
|
||||
@@ -80,11 +83,45 @@ zstd ABI:
|
||||
Rust parser through the `ZSTD_NOBENCH`-gated bridge in `zstdcli.c`.
|
||||
|
||||
The optimal block matcher, high-level frame compression, dictionary-building
|
||||
except suffix-array construction, legacy decoding callbacks, benchmark
|
||||
orchestration (`benchzstd`), and the CLI
|
||||
file-I/O backend are still C. They must move before the rewrite is complete.
|
||||
Keeping that boundary explicit prevents a passing hybrid build from being
|
||||
mistaken for the final all-Rust result.
|
||||
except suffix-array construction, the legacy v0.1-v0.7 decoders, benchmark
|
||||
orchestration (`benchzstd`), and the CLI file-I/O backend are still C. They
|
||||
must move before the rewrite is complete. Keeping that boundary explicit
|
||||
prevents a passing hybrid build from being mistaken for the final all-Rust
|
||||
result.
|
||||
|
||||
## Legacy decoding
|
||||
|
||||
Each `lib/legacy/zstd_v0N.c` file is a frozen snapshot of the entropy coders
|
||||
and frame logic of one historical release. The Rust ports in `src/legacy/`
|
||||
keep that property: every version owns its own frozen FSE/Huff0 and frame
|
||||
logic, ported line by line, and must never reuse the modern entropy modules
|
||||
or share code with other legacy versions. Outputs and error codes must be
|
||||
byte-identical to the original C files. Their only shared dependency is the
|
||||
`errors` module, matching the C files' `error_private.h` include.
|
||||
|
||||
Cargo features `legacy-v01` .. `legacy-v07` gate the per-version modules and
|
||||
are never default features. The build systems derive the feature list from
|
||||
the C configuration:
|
||||
|
||||
- `lib/Makefile` and `programs/Makefile` map `ZSTD_LEGACY_SUPPORT=N` to the
|
||||
features for versions >= N (0 disables legacy), matching the
|
||||
`ZSTD_LEGACY_FILES` selection in `lib/libzstd.mk`.
|
||||
- `tests/Makefile` always enables all seven features because the test
|
||||
objects compile every `lib/legacy/*.c` file regardless of dispatch level.
|
||||
- `build/meson` maps `legacy_level` like the makefiles; `build/cmake`
|
||||
enables all seven whenever `ZSTD_LEGACY_SUPPORT` is on because it always
|
||||
compiles all seven C files.
|
||||
|
||||
Every build system also encodes the legacy selection in the Rust target
|
||||
directory name (for example `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 that expects another.
|
||||
|
||||
A feature whose version has not been ported yet gates nothing; the original
|
||||
C file still provides that decoder, so mixed C/Rust legacy levels link
|
||||
cleanly. Porting a version means adding `src/legacy/zstd_v0N.rs`, registering
|
||||
it in `src/legacy/mod.rs` behind its feature, and reducing
|
||||
`lib/legacy/zstd_v0N.c` to a declaration-only shim.
|
||||
|
||||
## Compatibility boundary
|
||||
|
||||
|
||||
Reference in New Issue
Block a user