feat(compress): move literal compression policy to Rust

ZSTD_literalsCompressionIsDisabled() previously switched on the private
ZSTD_CCtx_params layout in a header inline helper. Replace that switch with a
scalar ABI call that extracts only literalCompressionMode, strategy, and
targetLength in C. The Rust helper preserves the enable and disable results,
the fast-strategy auto rule, and C's debug assertion plus release fallthrough
for invalid modes. Keep callers and compression state ownership in C, and
cover the policy truth table and debug invalid-mode invariant in Rust.

Test Plan:
- Compression-feature clippy for the library, benches, and tests before and
  after nightly formatting -- passed.
- `cargo +nightly fmt --manifest-path rust/Cargo.toml` -- passed.
- `cargo test --manifest-path rust/Cargo.toml --no-default-features
  --features compression zstd_compress_params` -- passed (43 tests).
- `make -B -C lib -j2 lib` -- passed.
- `make -C tests test-rust-lib-smoke` -- passed.
- `tests/fuzzer -s4560 -t47 -i48 -v` and `-s4560 -t56 -i57 -v` -- passed.
- `make -C tests -j2 test-zstream` -- passed (84 named, 5,416, and 8,387
  randomized cases).
- `git diff --check` and `git diff --cached --check` -- passed.
This commit is contained in:
2026-07-18 13:27:34 +02:00
parent 87a7cbdaec
commit adb6928f04
2 changed files with 78 additions and 11 deletions
+8 -11
View File
@@ -668,19 +668,16 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
return (srcSize >> minlog) + 2;
}
int ZSTD_rust_params_literalsCompressionIsDisabled(int literalCompressionMode,
int strategy,
U32 targetLength);
MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)
{
switch (cctxParams->literalCompressionMode) {
case ZSTD_ps_enable:
return 0;
case ZSTD_ps_disable:
return 1;
default:
assert(0 /* impossible: pre-validated */);
ZSTD_FALLTHROUGH;
case ZSTD_ps_auto:
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
}
return ZSTD_rust_params_literalsCompressionIsDisabled(
(int)cctxParams->literalCompressionMode,
(int)cctxParams->cParams.strategy,
cctxParams->cParams.targetLength);
}
/*! ZSTD_safecopyLiterals() :
+70
View File
@@ -449,6 +449,37 @@ pub extern "C" fn ZSTD_rust_params_resolveExternalSequenceValidation(mode: c_int
resolve_external_sequence_validation(mode)
}
#[inline]
fn literals_compression_is_disabled(
literal_compression_mode: c_int,
strategy: c_int,
target_length: u32,
) -> c_int {
match literal_compression_mode {
ZSTD_RUST_PS_ENABLE => 0,
ZSTD_RUST_PS_DISABLE => 1,
ZSTD_RUST_PS_AUTO => c_int::from(strategy == ZSTD_FAST && target_length > 0),
_ => {
debug_assert!(false, "invalid ZSTD_ParamSwitch_e literal mode");
c_int::from(strategy == ZSTD_FAST && target_length > 0)
}
}
}
/// C ABI for `ZSTD_literalsCompressionIsDisabled()`.
///
/// The C wrapper extracts these scalar fields so the private
/// `ZSTD_CCtx_params` layout does not cross the Rust boundary. Invalid modes
/// retain C's debug assertion and release-mode fallthrough to the auto policy.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_literalsCompressionIsDisabled(
literal_compression_mode: c_int,
strategy: c_int,
target_length: u32,
) -> c_int {
literals_compression_is_disabled(literal_compression_mode, strategy, target_length)
}
#[inline]
fn cdict_indices_are_tagged(cparams: ZSTD_compressionParameters) -> bool {
cparams.strategy == ZSTD_FAST || cparams.strategy == ZSTD_DFAST
@@ -1835,6 +1866,45 @@ mod tests {
}
}
#[test]
fn literal_compression_policy_matches_mode_strategy_and_target_length() {
for strategy in [ZSTD_FAST, ZSTD_DFAST, ZSTD_BTULTRA2] {
for target_length in [0, 1] {
assert_eq!(
ZSTD_rust_params_literalsCompressionIsDisabled(
ZSTD_RUST_PS_ENABLE,
strategy,
target_length,
),
0
);
assert_eq!(
ZSTD_rust_params_literalsCompressionIsDisabled(
ZSTD_RUST_PS_DISABLE,
strategy,
target_length,
),
1
);
assert_eq!(
ZSTD_rust_params_literalsCompressionIsDisabled(
ZSTD_RUST_PS_AUTO,
strategy,
target_length,
),
c_int::from(strategy == ZSTD_FAST && target_length > 0)
);
}
}
}
#[cfg(debug_assertions)]
#[test]
#[should_panic]
fn literal_compression_policy_rejects_invalid_mode_in_debug() {
literals_compression_is_disabled(99, ZSTD_FAST, 1);
}
#[test]
fn level_tables_match_representative_clevels_entries() {
let large = select_cparams(3, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_RUST_CPM_UNKNOWN);