From 3c51a978142d40cd50ab78790257e4cdcc6fd4d0 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sat, 18 Jul 2026 09:42:58 +0200 Subject: [PATCH] feat(compress): move CParamMode policy to Rust Keep C responsible for extracting the cdict and CCtx scalar fields while moving the attach-versus-copy mode decision into the Rust parameter module. The Rust ABI short-circuits absent cdicts and reuses the established attachment predicate, preserving unknown-size, force-attach, force-copy, and force-window behavior. Test Plan: - cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression cparam_mode_preserves_cdict_presence_and_attachment_policy -- passed - make -B -C lib -j2 lib -- passed - make -C tests -j2 fuzzer -- passed - ./tests/fuzzer -s4560 -t47 -i48 -v -- passed - Required clippy normal/benches/tests, nightly fmt, and diff checks -- passed --- lib/compress/zstd_compress.c | 19 +++++-- rust/src/zstd_compress_params.rs | 93 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3b716b4d0..5f606a8bb 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -134,6 +134,11 @@ U32 ZSTD_rust_params_dedicatedDictSearch_revertHashLog(U32 hashLog); int ZSTD_rust_params_shouldAttachDict(int strategy, int dedicatedDictSearch, U64 pledgedSrcSize, int attachDictPref, int forceWindow); +int ZSTD_rust_params_getCParamMode(int cdict_present, int cdict_strategy, + int cdict_dedicated_search, + U64 pledgedSrcSize, + int params_attachDictPref, + int params_forceWindow); /* CCtx parameter state is mirrored by rust/src/zstd_compress_params_api.rs. * Rust owns parameter bounds and clamping; C exposes only the @@ -4400,10 +4405,16 @@ size_t ZSTD_CStreamOutSize(void) static ZSTD_CParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize) { - if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) - return ZSTD_cpm_attachDict; - else - return ZSTD_cpm_noAttachDict; + int const cdict_present = cdict != NULL; + int const cdict_strategy = cdict_present ? cdict->matchState.cParams.strategy : 0; + int const cdict_dedicated_search = cdict_present ? cdict->matchState.dedicatedDictSearch : 0; + return (ZSTD_CParamMode_e)ZSTD_rust_params_getCParamMode( + cdict_present, + cdict_strategy, + cdict_dedicated_search, + pledgedSrcSize, + (int)params->attachDictPref, + params->forceWindow); } /* ZSTD_resetCStream(): diff --git a/rust/src/zstd_compress_params.rs b/rust/src/zstd_compress_params.rs index 591a9e96d..1ff5be9b0 100644 --- a/rust/src/zstd_compress_params.rs +++ b/rust/src/zstd_compress_params.rs @@ -485,6 +485,30 @@ fn should_attach_dict( && force_window == 0) } +#[inline] +fn get_cparam_mode( + cdict_present: c_int, + cdict_strategy: c_int, + cdict_dedicated_search: c_int, + pledged_src_size: u64, + params_attach_dict_pref: c_int, + params_force_window: c_int, +) -> c_int { + if cdict_present != 0 + && should_attach_dict( + cdict_strategy, + cdict_dedicated_search, + pledged_src_size, + params_attach_dict_pref, + params_force_window, + ) + { + ZSTD_RUST_CPM_ATTACH_DICT + } else { + ZSTD_RUST_CPM_NO_ATTACH_DICT + } +} + /// C ABI for `ZSTD_CDictIndicesAreTagged()`. #[no_mangle] pub extern "C" fn ZSTD_rust_params_cdictIndicesAreTagged( @@ -531,6 +555,26 @@ pub extern "C" fn ZSTD_rust_params_shouldAttachDict( )) } +/// C ABI for `ZSTD_getCParamMode()`. +#[no_mangle] +pub extern "C" fn ZSTD_rust_params_getCParamMode( + cdict_present: c_int, + cdict_strategy: c_int, + cdict_dedicated_search: c_int, + pledged_src_size: u64, + params_attach_dict_pref: c_int, + params_force_window: c_int, +) -> c_int { + get_cparam_mode( + cdict_present, + cdict_strategy, + cdict_dedicated_search, + pledged_src_size, + params_attach_dict_pref, + params_force_window, + ) +} + #[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. */ @@ -1468,6 +1512,55 @@ mod tests { ); } + #[test] + fn cparam_mode_preserves_cdict_presence_and_attachment_policy() { + assert_eq!( + ZSTD_rust_params_getCParamMode(0, ZSTD_FAST, 0, 1, ZSTD_DICT_FORCE_ATTACH, 0,), + ZSTD_RUST_CPM_NO_ATTACH_DICT + ); + assert_eq!( + ZSTD_rust_params_getCParamMode(1, ZSTD_FAST, 0, 8 * 1024, 0, 0), + ZSTD_RUST_CPM_ATTACH_DICT + ); + assert_eq!( + ZSTD_rust_params_getCParamMode( + 1, + ZSTD_FAST, + 0, + 8 * 1024 + 1, + ZSTD_DICT_FORCE_ATTACH, + 0, + ), + ZSTD_RUST_CPM_ATTACH_DICT + ); + assert_eq!( + ZSTD_rust_params_getCParamMode( + 1, + ZSTD_FAST, + 0, + ZSTD_CONTENTSIZE_UNKNOWN, + ZSTD_DICT_FORCE_COPY, + 0, + ), + ZSTD_RUST_CPM_NO_ATTACH_DICT + ); + assert_eq!( + ZSTD_rust_params_getCParamMode(1, ZSTD_FAST, 0, ZSTD_CONTENTSIZE_UNKNOWN, 0, 0,), + ZSTD_RUST_CPM_ATTACH_DICT + ); + assert_eq!( + ZSTD_rust_params_getCParamMode( + 1, + ZSTD_FAST, + 0, + ZSTD_CONTENTSIZE_UNKNOWN, + ZSTD_DICT_FORCE_ATTACH, + 1, + ), + ZSTD_RUST_CPM_NO_ATTACH_DICT + ); + } + #[test] fn external_sequence_validation_preserves_its_int_mode() { for mode in [c_int::MIN, -1, 0, 1, c_int::MAX] {