From f7c04292d4a61a7a9b7dd623e6d9a74380623eef Mon Sep 17 00:00:00 2001 From: ddidderr Date: Mon, 20 Jul 2026 06:43:45 +0200 Subject: [PATCH] refactor(compress): move advanced CDict wrapper policy to Rust Move advanced CDict parameter preparation and construction ordering into the Rust policy layer while keeping advanced2 allocation, workspace, and private context layout in C. Preserve the existing allocator and callback ABI at the seam. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets (782 passed) - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets (179 passed) - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test (all tests completed successfully) --- lib/compress/zstd_compress.c | 88 ++++++++++++-- rust/src/zstd_compress.rs | 222 +++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 9 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a0434e0b8..0e86adc40 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2678,6 +2678,42 @@ typedef char ZSTD_rust_create_cdict_advanced_state_layout[ == 15 * sizeof(void*) + 2 * sizeof(U32)) ? 1 : -1]; +typedef void (*ZSTD_rust_createCDictAdvancedWrapperInitParams_f)( + void* context, void* cctxParams, + const ZSTD_compressionParameters* cParams, + const void* customMem, size_t dictSize, int dictContentType); +typedef void* (*ZSTD_rust_createCDictAdvancedWrapperCreate_f)( + void* context, const void* dict, size_t dictSize, + int dictLoadMethod, int dictContentType, + const void* cctxParams, const void* customMem); +typedef struct { + void* callbackContext; + void* cctxParams; + const ZSTD_compressionParameters* cParams; + const void* customMem; + ZSTD_rust_createCDictAdvancedWrapperInitParams_f initParams; + ZSTD_rust_createCDictAdvancedWrapperCreate_f create; +} ZSTD_rust_createCDictAdvancedWrapperState; +void* ZSTD_rust_createCDictAdvancedWrapper( + const ZSTD_rust_createCDictAdvancedWrapperState* state, + const void* dict, size_t dictSize, + int dictLoadMethod, int dictContentType); +typedef char ZSTD_rust_create_cdict_advanced_wrapper_state_layout[ + (offsetof(ZSTD_rust_createCDictAdvancedWrapperState, callbackContext) == 0 + && offsetof(ZSTD_rust_createCDictAdvancedWrapperState, cctxParams) + == sizeof(void*) + && offsetof(ZSTD_rust_createCDictAdvancedWrapperState, cParams) + == 2 * sizeof(void*) + && offsetof(ZSTD_rust_createCDictAdvancedWrapperState, customMem) + == 3 * sizeof(void*) + && offsetof(ZSTD_rust_createCDictAdvancedWrapperState, initParams) + == 4 * sizeof(void*) + && offsetof(ZSTD_rust_createCDictAdvancedWrapperState, create) + == 5 * sizeof(void*) + && sizeof(ZSTD_rust_createCDictAdvancedWrapperState) + == 6 * sizeof(void*)) + ? 1 : -1]; + typedef size_t (*ZSTD_rust_compressBeginResetInternal_f)( void* context, const void* params, U64 pledgedSrcSize, size_t loadedDictSize, int zbuff); @@ -7040,6 +7076,39 @@ static void ZSTD_rust_createCDictAdvanced_free(void* context, void* cdict) ZSTD_freeCDict((ZSTD_CDict*)cdict); } +static void ZSTD_rust_createCDictAdvancedWrapper_initParams( + void* context, void* opaqueCctxParams, + const ZSTD_compressionParameters* cParams, + const void* opaqueCustomMem, size_t dictSize, int dictContentType) +{ + ZSTD_CCtx_params* const cctxParams = (ZSTD_CCtx_params*)opaqueCctxParams; + ZSTD_customMem const* const customMem = + (const ZSTD_customMem*)opaqueCustomMem; + (void)context; + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); + DEBUGLOG(3, "ZSTD_createCDict_advanced, dictSize=%u, mode=%u", + (unsigned)dictSize, (unsigned)dictContentType); + ZSTD_CCtxParams_init(cctxParams, 0); + cctxParams->cParams = *cParams; + cctxParams->customMem = *customMem; +} + +static void* ZSTD_rust_createCDictAdvancedWrapper_create( + void* context, const void* dict, size_t dictSize, + int dictLoadMethod, int dictContentType, + const void* opaqueCctxParams, const void* opaqueCustomMem) +{ + ZSTD_customMem const* const customMem = + (const ZSTD_customMem*)opaqueCustomMem; + (void)context; + return ZSTD_createCDict_advanced2( + dict, dictSize, + (ZSTD_dictLoadMethod_e)dictLoadMethod, + (ZSTD_dictContentType_e)dictContentType, + (const ZSTD_CCtx_params*)opaqueCctxParams, + *customMem); +} + ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, @@ -7047,15 +7116,16 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams; - ZSTD_memset(&cctxParams, 0, sizeof(cctxParams)); - DEBUGLOG(3, "ZSTD_createCDict_advanced, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); - ZSTD_CCtxParams_init(&cctxParams, 0); - cctxParams.cParams = cParams; - cctxParams.customMem = customMem; - return ZSTD_createCDict_advanced2( - dictBuffer, dictSize, - dictLoadMethod, dictContentType, - &cctxParams, customMem); + ZSTD_rust_createCDictAdvancedWrapperState state; + state.callbackContext = NULL; + state.cctxParams = &cctxParams; + state.cParams = &cParams; + state.customMem = &customMem; + state.initParams = ZSTD_rust_createCDictAdvancedWrapper_initParams; + state.create = ZSTD_rust_createCDictAdvancedWrapper_create; + return (ZSTD_CDict*)ZSTD_rust_createCDictAdvancedWrapper( + &state, dictBuffer, dictSize, + (int)dictLoadMethod, (int)dictContentType); } ZSTD_CDict* ZSTD_createCDict_advanced2( diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index faad252bd..098304439 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -2224,6 +2224,100 @@ pub unsafe extern "C" fn ZSTD_rust_createCCtx( cctx } +type CreateCDictAdvancedWrapperInitParamsFn = unsafe extern "C" fn( + *mut c_void, + *mut c_void, + *const ZSTD_compressionParameters, + *const c_void, + usize, + c_int, +); +type CreateCDictAdvancedWrapperCreateFn = unsafe extern "C" fn( + *mut c_void, + *const c_void, + usize, + c_int, + c_int, + *const c_void, + *const c_void, +) -> *mut c_void; + +/// Explicit projection for the public heap-CDict wrapper. +/// +/// Rust owns the wrapper's preparation-to-construction ordering and forwards +/// the dictionary scalars. C retains the private `ZSTD_CCtx_params` setup and +/// the advanced-CDict implementation behind callbacks; allocation and +/// workspace ownership stay in the existing advanced2 path. +#[repr(C)] +pub struct ZSTD_rust_createCDictAdvancedWrapperState { + callback_context: *mut c_void, + cctx_params: *mut c_void, + c_params: *const ZSTD_compressionParameters, + custom_mem: *const c_void, + init_params: CreateCDictAdvancedWrapperInitParamsFn, + create: CreateCDictAdvancedWrapperCreateFn, +} + +const _: () = { + assert!(offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, callback_context) == 0); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, cctx_params) == size_of::() + ); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, c_params) == 2 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, custom_mem) == 3 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, init_params) + == 4 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, create) == 5 * size_of::() + ); + assert!(size_of::() == size_of::<[usize; 6]>()); +}; + +/// Prepare a heap-CDict parameter object, then enter the existing advanced +/// construction path in the original callback order. +#[no_mangle] +pub unsafe extern "C" fn ZSTD_rust_createCDictAdvancedWrapper( + state: *const ZSTD_rust_createCDictAdvancedWrapperState, + dict: *const c_void, + dict_size: usize, + dict_load_method: c_int, + dict_content_type: c_int, +) -> *mut c_void { + if state.is_null() { + return ptr::null_mut(); + } + let state = unsafe { &*state }; + if state.cctx_params.is_null() || state.c_params.is_null() || state.custom_mem.is_null() { + return ptr::null_mut(); + } + + unsafe { + (state.init_params)( + state.callback_context, + state.cctx_params, + state.c_params, + state.custom_mem, + dict_size, + dict_content_type, + ); + (state.create)( + state.callback_context, + dict, + dict_size, + dict_load_method, + dict_content_type, + state.cctx_params, + state.custom_mem, + ) + } +} + type InitStaticCCtxFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void; const ZSTD_STATIC_WORKSPACE_ALIGNMENT: usize = 8; @@ -17800,6 +17894,134 @@ mod tests { assert!(context.initialized.is_null()); } + #[derive(Default)] + struct CreateCDictAdvancedWrapperTestContext { + events: Vec<&'static str>, + init_context: *mut c_void, + init_cctx_params: *mut c_void, + init_c_params: *const ZSTD_compressionParameters, + init_custom_mem: *const c_void, + init_dict_size: usize, + init_dict_content_type: c_int, + create_context: *mut c_void, + create_dict: *const c_void, + create_dict_size: usize, + create_dict_load_method: c_int, + create_dict_content_type: c_int, + create_cctx_params: *const c_void, + create_custom_mem: *const c_void, + result: *mut c_void, + } + + unsafe extern "C" fn create_cdict_advanced_wrapper_test_init( + context: *mut c_void, + cctx_params: *mut c_void, + c_params: *const ZSTD_compressionParameters, + custom_mem: *const c_void, + dict_size: usize, + dict_content_type: c_int, + ) { + let context = unsafe { &mut *context.cast::() }; + context.events.push("init"); + context.init_context = context as *mut _ as *mut c_void; + context.init_cctx_params = cctx_params; + context.init_c_params = c_params; + context.init_custom_mem = custom_mem; + context.init_dict_size = dict_size; + context.init_dict_content_type = dict_content_type; + } + + unsafe extern "C" fn create_cdict_advanced_wrapper_test_create( + context: *mut c_void, + dict: *const c_void, + dict_size: usize, + dict_load_method: c_int, + dict_content_type: c_int, + cctx_params: *const c_void, + custom_mem: *const c_void, + ) -> *mut c_void { + let context = unsafe { &mut *context.cast::() }; + context.events.push("create"); + context.create_context = context as *mut _ as *mut c_void; + context.create_dict = dict; + context.create_dict_size = dict_size; + context.create_dict_load_method = dict_load_method; + context.create_dict_content_type = dict_content_type; + context.create_cctx_params = cctx_params; + context.create_custom_mem = custom_mem; + context.result + } + + fn create_cdict_advanced_wrapper_test_state( + context: &mut CreateCDictAdvancedWrapperTestContext, + cctx_params: *mut c_void, + c_params: *const ZSTD_compressionParameters, + custom_mem: *const c_void, + ) -> ZSTD_rust_createCDictAdvancedWrapperState { + ZSTD_rust_createCDictAdvancedWrapperState { + callback_context: context as *mut _ as *mut c_void, + cctx_params, + c_params, + custom_mem, + init_params: create_cdict_advanced_wrapper_test_init, + create: create_cdict_advanced_wrapper_test_create, + } + } + + #[test] + fn create_cdict_advanced_wrapper_preserves_prepare_then_create_order() { + let mut context = CreateCDictAdvancedWrapperTestContext { + result: ptr::dangling_mut(), + ..Default::default() + }; + let cctx_params = ptr::dangling_mut::(); + let c_params = ptr::dangling::(); + let custom_mem = ptr::dangling::(); + let dict = ptr::dangling::().cast::(); + let state = create_cdict_advanced_wrapper_test_state( + &mut context, + cctx_params, + c_params, + custom_mem, + ); + + let result = unsafe { ZSTD_rust_createCDictAdvancedWrapper(&state, dict, 123, 1, 2) }; + + assert_eq!(result, context.result); + assert_eq!(context.events, ["init", "create"]); + assert_eq!(context.init_context, state.callback_context); + assert_eq!(context.init_cctx_params, cctx_params); + assert_eq!(context.init_c_params, c_params); + assert_eq!(context.init_custom_mem, custom_mem); + assert_eq!(context.init_dict_size, 123); + assert_eq!(context.init_dict_content_type, 2); + assert_eq!(context.create_context, state.callback_context); + assert_eq!(context.create_dict, dict); + assert_eq!(context.create_dict_size, 123); + assert_eq!(context.create_dict_load_method, 1); + assert_eq!(context.create_dict_content_type, 2); + assert_eq!(context.create_cctx_params, cctx_params); + assert_eq!(context.create_custom_mem, custom_mem); + } + + #[test] + fn create_cdict_advanced_wrapper_rejects_missing_parameter_storage() { + let mut context = CreateCDictAdvancedWrapperTestContext::default(); + let c_params = ptr::dangling::(); + let custom_mem = ptr::dangling::(); + let state = create_cdict_advanced_wrapper_test_state( + &mut context, + ptr::null_mut(), + c_params, + custom_mem, + ); + + let result = unsafe { ZSTD_rust_createCDictAdvancedWrapper(&state, ptr::null(), 0, 0, 0) }; + + assert!(result.is_null()); + assert!(context.events.is_empty()); + } + #[derive(Default)] struct InitCCtxTestContext { events: Vec<&'static str>,