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] {