From a3127511ce716693497fd78da796f89f9ba4934f Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sun, 19 Jul 2026 15:12:38 +0200 Subject: [PATCH] feat(compress): move begin dictionary policy into Rust Move shared compression-begin dictionary selection, CDict attach thresholds, reset ordering, insertion dispatch, and dictionary result publication into a Rust-owned ABI leaf. Keep CCtx reset, CDict attach, and private dictionary insertion behind C callbacks. Test Plan: - cargo test --manifest-path rust/Cargo.toml --lib - cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - make -B -C programs -j1 zstd - make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s - focused compress_begin unit tests --- lib/compress/zstd_compress.c | 160 +++++++++-- rust/src/zstd_compress_dictionary.rs | 400 +++++++++++++++++++++++++++ 2 files changed, 530 insertions(+), 30 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 935274622..f1d620a70 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1488,6 +1488,73 @@ typedef char ZSTD_rust_init_cdict_state_layout[ && sizeof(ZSTD_rust_initCDictState) == 19 * sizeof(void*)) ? 1 : -1]; +typedef size_t (*ZSTD_rust_compressBeginResetInternal_f)( + void* context, const void* params, U64 pledgedSrcSize, + size_t loadedDictSize, int zbuff); +typedef size_t (*ZSTD_rust_compressBeginResetUsingCDict_f)( + void* context, const void* cdict, const void* params, + U64 pledgedSrcSize, int zbuff); +typedef size_t (*ZSTD_rust_compressBeginInsertDictionary_f)( + void* context, const void* cdict, const void* dict, + size_t dictSize, int dictContentType, int dtlm); +typedef struct { + void* callbackContext; + const void* params; + const void* cdict; + const size_t* cdictContentSize; + const int* cdictCompressionLevel; + const ZSTD_dictAttachPref_e* attachDictPref; + const void* dict; + const size_t* dictSize; + const int* dictContentType; + const int* dtlm; + const U64* pledgedSrcSize; + const int* zbuff; + const int* forceLoad; + U32* dictID; + size_t* dictContentSize; + ZSTD_rust_compressBeginResetInternal_f resetInternal; + ZSTD_rust_compressBeginResetUsingCDict_f resetUsingCDict; + ZSTD_rust_compressBeginInsertDictionary_f insertDictionary; +} ZSTD_rust_compressBeginState; +size_t ZSTD_rust_compressBegin(const ZSTD_rust_compressBeginState* state); +typedef char ZSTD_rust_compress_begin_state_layout[ + (offsetof(ZSTD_rust_compressBeginState, callbackContext) == 0 + && offsetof(ZSTD_rust_compressBeginState, params) == sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, cdict) == 2 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, cdictContentSize) + == 3 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, cdictCompressionLevel) + == 4 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, attachDictPref) + == 5 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, dict) + == 6 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, dictSize) + == 7 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, dictContentType) + == 8 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, dtlm) + == 9 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, pledgedSrcSize) + == 10 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, zbuff) + == 11 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, forceLoad) + == 12 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, dictID) + == 13 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, dictContentSize) + == 14 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, resetInternal) + == 15 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, resetUsingCDict) + == 16 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, insertDictionary) + == 17 * sizeof(void*) + && sizeof(ZSTD_rust_compressBeginState) == 18 * sizeof(void*)) + ? 1 : -1]; + /* The sequence-compression loop receives only the state it actually reads or * updates. In particular, neither ZSTD_CCtx nor a C function pointer crosses * the Rust ABI. */ @@ -4470,6 +4537,45 @@ static size_t ZSTD_rust_initCDict_insertDictionary( ZSTD_tfp_forCDict, cdict->entropyWorkspace); } +static size_t ZSTD_rust_compressBegin_resetInternal( + void* context, const void* params, U64 pledgedSrcSize, + size_t loadedDictSize, int zbuff) +{ + return ZSTD_resetCCtx_internal( + (ZSTD_CCtx*)context, (const ZSTD_CCtx_params*)params, + pledgedSrcSize, loadedDictSize, ZSTDcrp_makeClean, + (ZSTD_buffered_policy_e)zbuff); +} + +static size_t ZSTD_rust_compressBegin_resetUsingCDict( + void* context, const void* cdict, const void* params, + U64 pledgedSrcSize, int zbuff) +{ + return ZSTD_resetCCtx_usingCDict( + (ZSTD_CCtx*)context, (const ZSTD_CDict*)cdict, + (const ZSTD_CCtx_params*)params, pledgedSrcSize, + (ZSTD_buffered_policy_e)zbuff); +} + +static size_t ZSTD_rust_compressBegin_insertDictionary( + void* context, const void* cdict, const void* dict, + size_t dictSize, int dictContentType, int dtlm) +{ + ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; + if (cdict != NULL) { + ZSTD_CDict const* const dictionary = (const ZSTD_CDict*)cdict; + dict = dictionary->dictContent; + dictSize = dictionary->dictContentSize; + dictContentType = (int)dictionary->dictContentType; + } + return ZSTD_compress_insertDictionary( + cctx->blockState.prevCBlock, &cctx->blockState.matchState, + &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, + dict, dictSize, (ZSTD_dictContentType_e)dictContentType, + (ZSTD_dictTableLoadMethod_e)dtlm, ZSTD_tfp_forCCtx, + cctx->tmpWorkspace); +} + #define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB) #define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL) @@ -4484,7 +4590,11 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - size_t const dictContentSize = cdict ? cdict->dictContentSize : dictSize; + ZSTD_rust_compressBeginState state; + int const dictContentTypeValue = (int)dictContentType; + int const dtlmValue = (int)dtlm; + int const zbuffValue = (int)zbuff; + int const forceLoadValue = (int)ZSTD_dictForceLoad; #if ZSTD_TRACE cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0; #endif @@ -4492,35 +4602,25 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, /* params are supposed to be fully validated at this point */ assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); assert(!((dict) && (cdict))); /* either dict or cdict, not both */ - if ( (cdict) - && (cdict->dictContentSize > 0) - && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF - || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER - || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0) - && (params->attachDictPref != ZSTD_dictForceLoad) ) { - return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); - } - - FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, - dictContentSize, - ZSTDcrp_makeClean, zbuff) , ""); - { size_t const dictID = cdict ? - ZSTD_compress_insertDictionary( - cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, - cdict->dictContentSize, cdict->dictContentType, dtlm, - ZSTD_tfp_forCCtx, cctx->tmpWorkspace) - : ZSTD_compress_insertDictionary( - cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, - dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->tmpWorkspace); - FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); - assert(dictID <= UINT_MAX); - cctx->dictID = (U32)dictID; - cctx->dictContentSize = dictContentSize; - } - return 0; + state.callbackContext = cctx; + state.params = params; + state.cdict = cdict; + state.cdictContentSize = cdict == NULL ? NULL : &cdict->dictContentSize; + state.cdictCompressionLevel = cdict == NULL ? NULL : &cdict->compressionLevel; + state.attachDictPref = ¶ms->attachDictPref; + state.dict = dict; + state.dictSize = &dictSize; + state.dictContentType = &dictContentTypeValue; + state.dtlm = &dtlmValue; + state.pledgedSrcSize = &pledgedSrcSize; + state.zbuff = &zbuffValue; + state.forceLoad = &forceLoadValue; + state.dictID = &cctx->dictID; + state.dictContentSize = &cctx->dictContentSize; + state.resetInternal = ZSTD_rust_compressBegin_resetInternal; + state.resetUsingCDict = ZSTD_rust_compressBegin_resetUsingCDict; + state.insertDictionary = ZSTD_rust_compressBegin_insertDictionary; + return ZSTD_rust_compressBegin(&state); } size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, diff --git a/rust/src/zstd_compress_dictionary.rs b/rust/src/zstd_compress_dictionary.rs index 1f6eb1286..e09cb5c00 100644 --- a/rust/src/zstd_compress_dictionary.rs +++ b/rust/src/zstd_compress_dictionary.rs @@ -404,6 +404,172 @@ pub unsafe extern "C" fn ZSTD_rust_initCDict( 0 } +type CompressBeginResetInternalFn = + unsafe extern "C" fn(*mut c_void, *const c_void, u64, usize, c_int) -> usize; +type CompressBeginResetUsingCDictFn = + unsafe extern "C" fn(*mut c_void, *const c_void, *const c_void, u64, c_int) -> usize; +type CompressBeginInsertDictionaryFn = + unsafe extern "C" fn(*mut c_void, *const c_void, *const c_void, usize, c_int, c_int) -> usize; + +/// Projection for the dictionary-selection portion of +/// `ZSTD_compressBegin_internal`. +/// +/// Rust owns the CDict attach decision and dictionary-result publication. C +/// retains the context reset, CDict attach, and private insertion callbacks. +#[repr(C)] +pub struct ZSTD_rust_compressBeginState { + callback_context: *mut c_void, + params: *const c_void, + cdict: *const c_void, + cdict_content_size: *const usize, + cdict_compression_level: *const c_int, + attach_dict_pref: *const c_int, + dict: *const c_void, + dict_size: *const usize, + dict_content_type: *const c_int, + dtlm: *const c_int, + pledged_src_size: *const u64, + zbuff: *const c_int, + force_load: *const c_int, + dict_id: *mut c_uint, + dict_content_size: *mut usize, + reset_internal: Option, + reset_using_cdict: Option, + insert_dictionary: Option, +} + +const _: () = { + assert!(size_of::() == size_of::()); + assert!(size_of::() == size_of::()); + assert!(size_of::() == size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, callback_context) == 0); + assert!(offset_of!(ZSTD_rust_compressBeginState, params) == size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, cdict) == 2 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, cdict_content_size) == 3 * size_of::()); + assert!( + offset_of!(ZSTD_rust_compressBeginState, cdict_compression_level) == 4 * size_of::() + ); + assert!(offset_of!(ZSTD_rust_compressBeginState, attach_dict_pref) == 5 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict) == 6 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_size) == 7 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_content_type) == size_of::<[usize; 8]>()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dtlm) == 9 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, pledged_src_size) == 10 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, zbuff) == 11 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, force_load) == size_of::<[usize; 12]>()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_id) == 13 * size_of::()); + assert!( + offset_of!(ZSTD_rust_compressBeginState, dict_content_size) == size_of::<[usize; 14]>() + ); + assert!(offset_of!(ZSTD_rust_compressBeginState, reset_internal) == 15 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, reset_using_cdict) == 16 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, insert_dictionary) == 17 * size_of::()); + assert!(size_of::() == size_of::<[usize; 18]>()); +}; + +/// Select and begin a dictionary-backed compression context. +#[no_mangle] +pub unsafe extern "C" fn ZSTD_rust_compressBegin( + state: *const ZSTD_rust_compressBeginState, +) -> usize { + if state.is_null() { + return ERROR(ZstdErrorCode::Generic); + } + let state = unsafe { &*state }; + let Some(reset_internal) = state.reset_internal else { + return ERROR(ZstdErrorCode::Generic); + }; + let Some(reset_using_cdict) = state.reset_using_cdict else { + return ERROR(ZstdErrorCode::Generic); + }; + let Some(insert_dictionary) = state.insert_dictionary else { + return ERROR(ZstdErrorCode::Generic); + }; + if state.callback_context.is_null() + || state.params.is_null() + || state.cdict_content_size.is_null() && !state.cdict.is_null() + || state.cdict_compression_level.is_null() && !state.cdict.is_null() + || state.attach_dict_pref.is_null() + || state.dict_size.is_null() + || state.dict_content_type.is_null() + || state.dtlm.is_null() + || state.pledged_src_size.is_null() + || state.zbuff.is_null() + || state.force_load.is_null() + || state.dict_id.is_null() + || state.dict_content_size.is_null() + { + return ERROR(ZstdErrorCode::Generic); + } + + let cdict_present = !state.cdict.is_null(); + let pledged_src_size = unsafe { *state.pledged_src_size }; + let dict_content_size = if cdict_present { + unsafe { *state.cdict_content_size } + } else { + unsafe { *state.dict_size } + }; + let cdict_compression_level = if cdict_present { + unsafe { *state.cdict_compression_level } + } else { + 0 + }; + let should_attach = cdict_present + && dict_content_size > 0 + && (pledged_src_size < CDICT_PARAMS_SRC_SIZE_CUTOFF + || pledged_src_size + < (dict_content_size as u64).wrapping_mul(CDICT_PARAMS_DICT_SIZE_MULTIPLIER) + || pledged_src_size == ZSTD_CONTENTSIZE_UNKNOWN + || cdict_compression_level == 0) + && unsafe { *state.attach_dict_pref } != unsafe { *state.force_load }; + if should_attach { + return unsafe { + reset_using_cdict( + state.callback_context, + state.cdict, + state.params, + pledged_src_size, + *state.zbuff, + ) + }; + } + + let reset_result = unsafe { + reset_internal( + state.callback_context, + state.params, + pledged_src_size, + dict_content_size, + *state.zbuff, + ) + }; + if ERR_isError(reset_result) { + return reset_result; + } + + let dict_id = unsafe { + insert_dictionary( + state.callback_context, + state.cdict, + state.dict, + *state.dict_size, + *state.dict_content_type, + *state.dtlm, + ) + }; + if ERR_isError(dict_id) { + return dict_id; + } + if dict_id > c_uint::MAX as usize { + return ERROR(ZstdErrorCode::Generic); + } + unsafe { + *state.dict_id = dict_id as c_uint; + *state.dict_content_size = dict_content_size; + } + 0 +} + /// Scalar projections for the public CDict query helpers. #[repr(C)] pub struct ZSTD_rust_cdictQueryState { @@ -1100,6 +1266,240 @@ mod tests { assert_eq!(content_size_flag, 1); } + struct CompressBeginProbe { + events: Vec<&'static str>, + reset_params: *const c_void, + reset_loaded_dict_size: usize, + reset_pledged_src_size: u64, + reset_zbuff: c_int, + reset_result: usize, + attach_cdict: *const c_void, + attach_params: *const c_void, + attach_pledged_src_size: u64, + attach_zbuff: c_int, + attach_result: usize, + insert_cdict: *const c_void, + insert_dict: *const c_void, + insert_size: usize, + insert_content_type: c_int, + insert_dtlm: c_int, + insert_result: usize, + } + + impl Default for CompressBeginProbe { + fn default() -> Self { + Self { + events: Vec::new(), + reset_params: ptr::null(), + reset_loaded_dict_size: 0, + reset_pledged_src_size: 0, + reset_zbuff: 0, + reset_result: 0, + attach_cdict: ptr::null(), + attach_params: ptr::null(), + attach_pledged_src_size: 0, + attach_zbuff: 0, + attach_result: 0, + insert_cdict: ptr::null(), + insert_dict: ptr::null(), + insert_size: 0, + insert_content_type: 0, + insert_dtlm: 0, + insert_result: 0, + } + } + } + + unsafe fn compress_begin_probe(context: *mut c_void) -> &'static mut CompressBeginProbe { + unsafe { &mut *context.cast::() } + } + + unsafe extern "C" fn compress_begin_reset_internal( + context: *mut c_void, + params: *const c_void, + pledged_src_size: u64, + loaded_dict_size: usize, + zbuff: c_int, + ) -> usize { + let probe = unsafe { compress_begin_probe(context) }; + probe.events.push("reset"); + probe.reset_params = params; + probe.reset_pledged_src_size = pledged_src_size; + probe.reset_loaded_dict_size = loaded_dict_size; + probe.reset_zbuff = zbuff; + probe.reset_result + } + + unsafe extern "C" fn compress_begin_reset_using_cdict( + context: *mut c_void, + cdict: *const c_void, + params: *const c_void, + pledged_src_size: u64, + zbuff: c_int, + ) -> usize { + let probe = unsafe { compress_begin_probe(context) }; + probe.events.push("attach"); + probe.attach_cdict = cdict; + probe.attach_params = params; + probe.attach_pledged_src_size = pledged_src_size; + probe.attach_zbuff = zbuff; + probe.attach_result + } + + unsafe extern "C" fn compress_begin_insert_dictionary( + context: *mut c_void, + cdict: *const c_void, + dict: *const c_void, + dict_size: usize, + dict_content_type: c_int, + dtlm: c_int, + ) -> usize { + let probe = unsafe { compress_begin_probe(context) }; + probe.events.push("insert"); + probe.insert_cdict = cdict; + probe.insert_dict = dict; + probe.insert_size = dict_size; + probe.insert_content_type = dict_content_type; + probe.insert_dtlm = dtlm; + probe.insert_result + } + + #[allow(clippy::too_many_arguments)] + fn compress_begin_test_state( + probe: &mut CompressBeginProbe, + params: *const c_void, + cdict: *const c_void, + cdict_content_size: *const usize, + cdict_compression_level: *const c_int, + attach_dict_pref: &c_int, + dict: *const c_void, + dict_size: &usize, + dict_content_type: &c_int, + dtlm: &c_int, + pledged_src_size: &u64, + zbuff: &c_int, + force_load: &c_int, + dict_id: &mut c_uint, + dict_content_size: &mut usize, + ) -> ZSTD_rust_compressBeginState { + ZSTD_rust_compressBeginState { + callback_context: (probe as *mut CompressBeginProbe).cast(), + params, + cdict, + cdict_content_size, + cdict_compression_level, + attach_dict_pref, + dict, + dict_size, + dict_content_type, + dtlm, + pledged_src_size, + zbuff, + force_load, + dict_id, + dict_content_size, + reset_internal: Some(compress_begin_reset_internal), + reset_using_cdict: Some(compress_begin_reset_using_cdict), + insert_dictionary: Some(compress_begin_insert_dictionary), + } + } + + #[test] + fn compress_begin_resets_then_inserts_for_loaded_dictionary() { + let dictionary = [1u8, 2, 3, 4]; + let mut probe = CompressBeginProbe { + insert_result: 17, + ..Default::default() + }; + let params = 0x3000usize as *const c_void; + let attach_dict_pref = 0; + let dict_size = dictionary.len(); + let dict_content_type = ZSTD_DCT_RAW_CONTENT; + let dtlm = 7; + let pledged_src_size = 1u64 << 20; + let zbuff = 9; + let force_load = 1; + let mut dict_id = 0; + let mut dict_content_size = 0; + let state = compress_begin_test_state( + &mut probe, + params, + ptr::null(), + ptr::null(), + ptr::null(), + &attach_dict_pref, + dictionary.as_ptr().cast(), + &dict_size, + &dict_content_type, + &dtlm, + &pledged_src_size, + &zbuff, + &force_load, + &mut dict_id, + &mut dict_content_size, + ); + + let result = unsafe { ZSTD_rust_compressBegin(&state) }; + + assert_eq!(result, 0); + assert_eq!(probe.events, ["reset", "insert"]); + assert_eq!(probe.reset_params, params); + assert_eq!(probe.reset_loaded_dict_size, dictionary.len()); + assert_eq!(probe.reset_pledged_src_size, pledged_src_size); + assert_eq!(probe.reset_zbuff, zbuff); + assert!(probe.insert_cdict.is_null()); + assert_eq!(probe.insert_dict, dictionary.as_ptr().cast()); + assert_eq!(probe.insert_size, dictionary.len()); + assert_eq!(probe.insert_content_type, dict_content_type); + assert_eq!(probe.insert_dtlm, dtlm); + assert_eq!(dict_id, probe.insert_result as c_uint); + assert_eq!(dict_content_size, dictionary.len()); + } + + #[test] + fn compress_begin_attaches_small_cdict_without_insertion() { + let mut probe = CompressBeginProbe::default(); + let params = 0x3000usize as *const c_void; + let cdict = 0x4000usize as *const c_void; + let cdict_content_size = 16; + let cdict_compression_level = 0; + let attach_dict_pref = 0; + let dict_size = 0; + let dict_content_type = ZSTD_DCT_AUTO; + let dtlm = 7; + let pledged_src_size = ZSTD_CONTENTSIZE_UNKNOWN; + let zbuff = 9; + let force_load = 1; + let mut dict_id = 0; + let mut dict_content_size = 0; + let state = compress_begin_test_state( + &mut probe, + params, + cdict, + &cdict_content_size, + &cdict_compression_level, + &attach_dict_pref, + ptr::null(), + &dict_size, + &dict_content_type, + &dtlm, + &pledged_src_size, + &zbuff, + &force_load, + &mut dict_id, + &mut dict_content_size, + ); + + let result = unsafe { ZSTD_rust_compressBegin(&state) }; + + assert_eq!(result, 0); + assert_eq!(probe.events, ["attach"]); + assert_eq!(probe.attach_cdict, cdict); + assert_eq!(probe.attach_params, params); + assert_eq!(probe.attach_pledged_src_size, pledged_src_size); + assert_eq!(probe.attach_zbuff, zbuff); + } + unsafe fn cctx_policy_probe(context: *mut c_void) -> &'static mut CctxPolicyProbe { unsafe { &mut *context.cast::() } }