From c86d18be81fd37e7bf3c7e22133d4d85d4254f01 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sat, 18 Jul 2026 09:07:42 +0200 Subject: [PATCH] feat(compress): move dedicated dict support predicate to Rust Dedicated dictionary search support is a pure compression-parameter policy check. Move its strategy and hash/chain-log comparisons into the Rust parameter module behind a by-value ZSTD_compressionParameters ABI, while leaving the existing C fallback path in createCDict_advanced2 unchanged. Test Plan: - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression dedicated_dict_search_support_matches_strategy_and_log_boundaries` -- passed - `make -B -C lib -j2 lib` -- passed - `make -C tests -j2 fuzzer` -- passed - `./tests/fuzzer -s4560 -t47 -i48 -v` -- passed - `cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression` -- passed - The same clippy command with `--benches` and `--tests` -- passed - `cargo +nightly fmt --manifest-path rust/Cargo.toml` -- passed - `git diff --cached --check` -- passed --- lib/compress/zstd_compress.c | 14 ++----------- rust/src/zstd_compress_params.rs | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 198078c00..ce45c5de4 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -121,6 +121,7 @@ int ZSTD_rust_params_resolveEnableLdm( int mode, ZSTD_compressionParameters cParams); int ZSTD_rust_params_resolveExternalRepcodeSearch(int mode, int cLevel); int ZSTD_rust_params_cdictIndicesAreTagged(ZSTD_compressionParameters cParams); +int ZSTD_rust_params_dedicatedDictSearchIsSupported(ZSTD_compressionParameters cParams); /* CCtx parameter state is mirrored by rust/src/zstd_compress_params_api.rs. * Rust owns parameter bounds and clamping; C exposes only the @@ -912,8 +913,6 @@ size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSr static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( int const compressionLevel, size_t const dictSize); -static int ZSTD_dedicatedDictSearch_isSupported( - const ZSTD_compressionParameters* cParams); static void ZSTD_dedicatedDictSearch_revertCParams( ZSTD_compressionParameters* cParams); @@ -4131,7 +4130,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); } - if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) { + if (!ZSTD_rust_params_dedicatedDictSearchIsSupported(cParams)) { /* Fall back to non-DDSS params */ cctxParams.enableDedicatedDictSearch = 0; cParams = ZSTD_getCParamsFromCCtxParams( @@ -5675,15 +5674,6 @@ static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const return cParams; } -static int ZSTD_dedicatedDictSearch_isSupported( - ZSTD_compressionParameters const* cParams) -{ - return (cParams->strategy >= ZSTD_greedy) - && (cParams->strategy <= ZSTD_lazy2) - && (cParams->hashLog > cParams->chainLog) - && (cParams->chainLog <= 24); -} - /** * Reverses the adjustment applied to cparams when enabling dedicated dict * search. This is used to recover the params set to be used in the working diff --git a/rust/src/zstd_compress_params.rs b/rust/src/zstd_compress_params.rs index 422c467cc..7daf98d0a 100644 --- a/rust/src/zstd_compress_params.rs +++ b/rust/src/zstd_compress_params.rs @@ -431,6 +431,14 @@ fn cdict_indices_are_tagged(cparams: ZSTD_compressionParameters) -> bool { cparams.strategy == ZSTD_FAST || cparams.strategy == ZSTD_DFAST } +#[inline] +fn dedicated_dict_search_is_supported(cparams: ZSTD_compressionParameters) -> bool { + cparams.strategy >= ZSTD_GREEDY + && cparams.strategy <= ZSTD_LAZY2 + && cparams.hashLog > cparams.chainLog + && cparams.chainLog <= 24 +} + /// C ABI for `ZSTD_CDictIndicesAreTagged()`. #[no_mangle] pub extern "C" fn ZSTD_rust_params_cdictIndicesAreTagged( @@ -439,6 +447,14 @@ pub extern "C" fn ZSTD_rust_params_cdictIndicesAreTagged( c_int::from(cdict_indices_are_tagged(cparams)) } +/// C ABI for `ZSTD_dedicatedDictSearch_isSupported()`. +#[no_mangle] +pub extern "C" fn ZSTD_rust_params_dedicatedDictSearchIsSupported( + cparams: ZSTD_compressionParameters, +) -> c_int { + c_int::from(dedicated_dict_search_is_supported(cparams)) +} + #[inline] fn dict_and_window_log(window_log: u32, src_size: u64, dict_size: u64) -> u32 { /* 1ULL << ZSTD_WINDOWLOG_MAX, which is smaller for 32-bit builds. */ @@ -1224,6 +1240,24 @@ mod tests { ); } + #[test] + fn dedicated_dict_search_support_matches_strategy_and_log_boundaries() { + let supported = |strategy, chain_log, hash_log| { + ZSTD_rust_params_dedicatedDictSearchIsSupported(ZSTD_compressionParameters { + strategy, + chainLog: chain_log, + hashLog: hash_log, + ..ZSTD_compressionParameters::default() + }) + }; + + assert_eq!(supported(ZSTD_GREEDY, 24, 25), 1); + assert_eq!(supported(ZSTD_LAZY2, 24, 25), 1); + assert_eq!(supported(ZSTD_BTLAZY2, 24, 25), 0); + assert_eq!(supported(ZSTD_LAZY2, 24, 24), 0); + assert_eq!(supported(ZSTD_LAZY2, 25, 26), 0); + } + #[test] fn external_sequence_validation_preserves_its_int_mode() { for mode in [c_int::MIN, -1, 0, 1, c_int::MAX] {