feat(compress): move dedicated dict get params to Rust

Port the final strategy-dependent transform in
ZSTD_dedicatedDictSearch_getCParams to a Rust ABI leaf that accepts and
returns the complete repr(C) compression-parameter struct. Keep C responsible
for ZSTD_getCParams_internal table selection and adjustment, including the
createCDict mode and its existing call order, as well as all dictionary and
context construction. The Rust leaf changes only hashLog for greedy, lazy,
and lazy2; every other and unexpected strategy is preserved unchanged.

Remove the obsolete scalar hash-log C ABI now that the complete-parameter
boundary is used. The focused Rust tests cover every strategy class and
unexpected values, field preservation, wrapping adjustment boundaries, and
the existing reverse transform's subtraction/clamp behavior.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression zstd_compress_params` -- passed (37 tests)
- `cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression` -- passed before and after formatting
- `cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression --benches` -- passed before and after formatting
- `cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression --tests` -- passed before and after formatting
- `cargo +nightly fmt --manifest-path rust/Cargo.toml` -- passed
- `make -B -C lib -j2 lib` -- passed
- `make -C tests test-rust-lib-smoke` -- passed
- `make -B -C tests -j2 fuzzer` -- passed
- `tests/fuzzer -s4560 -t56 -i57 -v` -- passed
- `make -C tests -j2 test-zstream` -- passed (84 named tests; randomized phases of 6,557 and 7,884 cases)
- `git diff --check` and `git diff --cached --check` -- passed
This commit is contained in:
2026-07-18 10:56:28 +02:00
parent a895506e78
commit 21431587fa
2 changed files with 95 additions and 23 deletions
+90 -5
View File
@@ -448,6 +448,19 @@ fn dedicated_dict_search_get_hash_log(hash_log: u32) -> u32 {
hash_log.wrapping_add(ZSTD_LAZY_DDSS_BUCKET_LOG)
}
#[inline]
fn dedicated_dict_search_get_cparams(
mut cparams: ZSTD_compressionParameters,
) -> ZSTD_compressionParameters {
match cparams.strategy {
ZSTD_GREEDY | ZSTD_LAZY | ZSTD_LAZY2 => {
cparams.hashLog = dedicated_dict_search_get_hash_log(cparams.hashLog);
}
_ => {}
}
cparams
}
#[inline]
fn dedicated_dict_search_revert_hash_log(hash_log: u32) -> u32 {
hash_log
@@ -538,10 +551,12 @@ pub extern "C" fn ZSTD_rust_params_dedicatedDictSearchIsSupported(
c_int::from(dedicated_dict_search_is_supported(cparams))
}
/// C ABI for the hash-log adjustment used by `ZSTD_dedicatedDictSearch_getCParams()`.
/// C ABI for `ZSTD_dedicatedDictSearch_getCParams()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_dedicatedDictSearch_getHashLog(hash_log: u32) -> u32 {
dedicated_dict_search_get_hash_log(hash_log)
pub extern "C" fn ZSTD_rust_params_dedicatedDictSearch_getCParams(
cparams: ZSTD_compressionParameters,
) -> ZSTD_compressionParameters {
dedicated_dict_search_get_cparams(cparams)
}
/// C ABI for `ZSTD_dedicatedDictSearch_revertCParams()`.
@@ -1437,7 +1452,7 @@ mod tests {
let should_adjust = matches!(strategy, ZSTD_GREEDY | ZSTD_LAZY | ZSTD_LAZY2);
let original = 12;
let adjusted = if should_adjust {
ZSTD_rust_params_dedicatedDictSearch_getHashLog(original)
dedicated_dict_search_get_hash_log(original)
} else {
original
};
@@ -1451,7 +1466,7 @@ mod tests {
assert_eq!(reverted, original);
}
assert_eq!(ZSTD_rust_params_dedicatedDictSearch_getHashLog(u32::MAX), 1);
assert_eq!(dedicated_dict_search_get_hash_log(u32::MAX), 1);
assert_eq!(
dedicated_dict_search_revert_hash_log(ZSTD_HASHLOG_MIN as u32),
ZSTD_HASHLOG_MIN as u32
@@ -1468,6 +1483,76 @@ mod tests {
assert_eq!(dedicated_dict_search_revert_hash_log(1), u32::MAX);
}
#[test]
fn dedicated_dict_search_get_cparams_preserves_fields_and_strategy_policy() {
let strategies = [
ZSTD_FAST,
ZSTD_DFAST,
ZSTD_GREEDY,
ZSTD_LAZY,
ZSTD_LAZY2,
ZSTD_BTLAZY2,
ZSTD_BTOPT,
ZSTD_BTULTRA,
ZSTD_BTULTRA2,
-1,
99,
];
for strategy in strategies {
let input = ZSTD_compressionParameters {
windowLog: 21,
chainLog: 19,
hashLog: 12,
searchLog: 5,
minMatch: 4,
targetLength: 48,
strategy,
};
let output = ZSTD_rust_params_dedicatedDictSearch_getCParams(input);
let expected_hash_log = if matches!(strategy, ZSTD_GREEDY | ZSTD_LAZY | ZSTD_LAZY2) {
14
} else {
input.hashLog
};
assert_eq!(output.hashLog, expected_hash_log, "strategy {strategy}");
assert_eq!(output.windowLog, input.windowLog, "strategy {strategy}");
assert_eq!(output.chainLog, input.chainLog, "strategy {strategy}");
assert_eq!(output.searchLog, input.searchLog, "strategy {strategy}");
assert_eq!(output.minMatch, input.minMatch, "strategy {strategy}");
assert_eq!(
output.targetLength, input.targetLength,
"strategy {strategy}"
);
assert_eq!(output.strategy, input.strategy, "strategy {strategy}");
}
for strategy in [ZSTD_GREEDY, ZSTD_LAZY, ZSTD_LAZY2] {
let mut input = ZSTD_compressionParameters {
hashLog: u32::MAX,
strategy,
..ZSTD_compressionParameters::default()
};
assert_eq!(
ZSTD_rust_params_dedicatedDictSearch_getCParams(input).hashLog,
1
);
input.hashLog = 0;
assert_eq!(
ZSTD_rust_params_dedicatedDictSearch_getCParams(input).hashLog,
2
);
input.hashLog = 1;
assert_eq!(
ZSTD_rust_params_dedicatedDictSearch_getCParams(input).hashLog,
3
);
}
}
#[test]
fn dedicated_dict_search_revert_cparams_preserves_fields_and_strategy_policy() {
let strategies = [