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:
@@ -668,19 +668,16 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
|
|||||||
return (srcSize >> minlog) + 2;
|
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)
|
MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)
|
||||||
{
|
{
|
||||||
switch (cctxParams->literalCompressionMode) {
|
return ZSTD_rust_params_literalsCompressionIsDisabled(
|
||||||
case ZSTD_ps_enable:
|
(int)cctxParams->literalCompressionMode,
|
||||||
return 0;
|
(int)cctxParams->cParams.strategy,
|
||||||
case ZSTD_ps_disable:
|
cctxParams->cParams.targetLength);
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
assert(0 /* impossible: pre-validated */);
|
|
||||||
ZSTD_FALLTHROUGH;
|
|
||||||
case ZSTD_ps_auto:
|
|
||||||
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! ZSTD_safecopyLiterals() :
|
/*! ZSTD_safecopyLiterals() :
|
||||||
|
|||||||
@@ -449,6 +449,37 @@ pub extern "C" fn ZSTD_rust_params_resolveExternalSequenceValidation(mode: c_int
|
|||||||
resolve_external_sequence_validation(mode)
|
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]
|
#[inline]
|
||||||
fn cdict_indices_are_tagged(cparams: ZSTD_compressionParameters) -> bool {
|
fn cdict_indices_are_tagged(cparams: ZSTD_compressionParameters) -> bool {
|
||||||
cparams.strategy == ZSTD_FAST || cparams.strategy == ZSTD_DFAST
|
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]
|
#[test]
|
||||||
fn level_tables_match_representative_clevels_entries() {
|
fn level_tables_match_representative_clevels_entries() {
|
||||||
let large = select_cparams(3, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_RUST_CPM_UNKNOWN);
|
let large = select_cparams(3, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_RUST_CPM_UNKNOWN);
|
||||||
|
|||||||
Reference in New Issue
Block a user