diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 88ef4d486..d7f679a4f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -404,12 +404,23 @@ typedef char ZSTD_rust_free_cdict_state_layout[ == 3 * sizeof(void*) && sizeof(ZSTD_rust_freeCDictState) == 4 * sizeof(void*)) ? 1 : -1]; -typedef void* (*ZSTD_rust_initStaticCDictInit_f)(void* context); +typedef void (*ZSTD_rust_initStaticCDictCreateWorkspace_f)(void* context); +typedef void* (*ZSTD_rust_initStaticCDictReserveObject_f)(void* context); +typedef void (*ZSTD_rust_initStaticCDictMoveWorkspace_f)( + void* context, void* cdict); +typedef void (*ZSTD_rust_initStaticCDictInitialize_f)( + void* context, void* cdict); +typedef void* (*ZSTD_rust_initStaticCDictInit_f)( + void* context, void* cdict); typedef struct { void* callbackContext; void* workspace; size_t workspaceSize; size_t neededSize; + ZSTD_rust_initStaticCDictCreateWorkspace_f createWorkspace; + ZSTD_rust_initStaticCDictReserveObject_f reserveObject; + ZSTD_rust_initStaticCDictMoveWorkspace_f moveWorkspace; + ZSTD_rust_initStaticCDictInitialize_f initialize; ZSTD_rust_initStaticCDictInit_f init; } ZSTD_rust_initStaticCDictState; void* ZSTD_rust_initStaticCDict(const ZSTD_rust_initStaticCDictState* state); @@ -421,9 +432,17 @@ typedef char ZSTD_rust_init_static_cdict_state_layout[ == 2 * sizeof(void*) && offsetof(ZSTD_rust_initStaticCDictState, neededSize) == 3 * sizeof(void*) - && offsetof(ZSTD_rust_initStaticCDictState, init) + && offsetof(ZSTD_rust_initStaticCDictState, createWorkspace) == 4 * sizeof(void*) - && sizeof(ZSTD_rust_initStaticCDictState) == 5 * sizeof(void*)) + && offsetof(ZSTD_rust_initStaticCDictState, reserveObject) + == 5 * sizeof(void*) + && offsetof(ZSTD_rust_initStaticCDictState, moveWorkspace) + == 6 * sizeof(void*) + && offsetof(ZSTD_rust_initStaticCDictState, initialize) + == 7 * sizeof(void*) + && offsetof(ZSTD_rust_initStaticCDictState, init) + == 8 * sizeof(void*) + && sizeof(ZSTD_rust_initStaticCDictState) == 9 * sizeof(void*)) ? 1 : -1]; typedef void (*ZSTD_rust_resetCCtxClearAllDicts_f)(void* context); typedef size_t (*ZSTD_rust_resetCCtxResetParams_f)(void* context); @@ -2531,11 +2550,14 @@ typedef size_t (*ZSTD_rust_createCDictAdvancedWorkspaceSize_f)( int useRowMatchFinder, int enableDedicatedDictSearch); typedef void* (*ZSTD_rust_createCDictAdvancedAllocate_f)( void* context, size_t workspaceSize); -typedef void* (*ZSTD_rust_createCDictAdvancedCreate_f)( - void* context, void* workspace, size_t workspaceSize, - size_t dictSize, int dictLoadMethod, - const ZSTD_compressionParameters* cParams, - int useRowMatchFinder, int enableDedicatedDictSearch); +typedef void (*ZSTD_rust_createCDictAdvancedCreateWorkspace_f)( + void* context, void* workspace, size_t workspaceSize); +typedef void* (*ZSTD_rust_createCDictAdvancedReserveObject_f)( + void* context); +typedef void (*ZSTD_rust_createCDictAdvancedMoveWorkspace_f)( + void* context, void* cdict); +typedef void (*ZSTD_rust_createCDictAdvancedInitialize_f)( + void* context, void* cdict, int useRowMatchFinder); typedef size_t (*ZSTD_rust_createCDictAdvancedInit_f)( void* context, void* cdict, const void* dict, size_t dictSize, int dictLoadMethod, int dictContentType, @@ -2555,7 +2577,10 @@ typedef struct { ZSTD_rust_createCDictAdvancedValidateCustomMem_f validateCustomMem; ZSTD_rust_createCDictAdvancedWorkspaceSize_f workspaceSize; ZSTD_rust_createCDictAdvancedAllocate_f allocate; - ZSTD_rust_createCDictAdvancedCreate_f create; + ZSTD_rust_createCDictAdvancedCreateWorkspace_f createWorkspace; + ZSTD_rust_createCDictAdvancedReserveObject_f reserveObject; + ZSTD_rust_createCDictAdvancedMoveWorkspace_f moveWorkspace; + ZSTD_rust_createCDictAdvancedInitialize_f initialize; ZSTD_rust_createCDictAdvancedInit_f init; ZSTD_rust_createCDictAdvancedFreeWorkspace_f freeWorkspace; ZSTD_rust_createCDictAdvancedFree_f free; @@ -2584,16 +2609,22 @@ typedef char ZSTD_rust_create_cdict_advanced_state_layout[ == 6 * sizeof(void*) + 2 * sizeof(U32) && offsetof(ZSTD_rust_createCDictAdvancedState, allocate) == 7 * sizeof(void*) + 2 * sizeof(U32) - && offsetof(ZSTD_rust_createCDictAdvancedState, create) + && offsetof(ZSTD_rust_createCDictAdvancedState, createWorkspace) == 8 * sizeof(void*) + 2 * sizeof(U32) - && offsetof(ZSTD_rust_createCDictAdvancedState, init) + && offsetof(ZSTD_rust_createCDictAdvancedState, reserveObject) == 9 * sizeof(void*) + 2 * sizeof(U32) - && offsetof(ZSTD_rust_createCDictAdvancedState, freeWorkspace) + && offsetof(ZSTD_rust_createCDictAdvancedState, moveWorkspace) == 10 * sizeof(void*) + 2 * sizeof(U32) - && offsetof(ZSTD_rust_createCDictAdvancedState, free) + && offsetof(ZSTD_rust_createCDictAdvancedState, initialize) == 11 * sizeof(void*) + 2 * sizeof(U32) + && offsetof(ZSTD_rust_createCDictAdvancedState, init) + == 12 * sizeof(void*) + 2 * sizeof(U32) + && offsetof(ZSTD_rust_createCDictAdvancedState, freeWorkspace) + == 13 * sizeof(void*) + 2 * sizeof(U32) + && offsetof(ZSTD_rust_createCDictAdvancedState, free) + == 14 * sizeof(void*) + 2 * sizeof(U32) && sizeof(ZSTD_rust_createCDictAdvancedState) - == 12 * sizeof(void*) + 2 * sizeof(U32)) + == 15 * sizeof(void*) + 2 * sizeof(U32)) ? 1 : -1]; typedef size_t (*ZSTD_rust_compressBeginResetInternal_f)( @@ -6710,9 +6741,16 @@ static size_t ZSTD_initCDict_internal( (int)dictLoadMethod, (int)dictContentType); } +typedef struct { + ZSTD_customMem customMem; + ZSTD_cwksp workspace; +} ZSTD_rust_createCDictAdvancedContext; + static int ZSTD_rust_createCDictAdvanced_validateCustomMem(void* context) { - ZSTD_customMem const* const customMem = (const ZSTD_customMem*)context; + ZSTD_rust_createCDictAdvancedContext const* const createContext = + (const ZSTD_rust_createCDictAdvancedContext*)context; + ZSTD_customMem const* const customMem = &createContext->customMem; return ((!customMem->customAlloc) ^ (!customMem->customFree)) == 0; } @@ -6741,59 +6779,54 @@ static size_t ZSTD_rust_createCDictAdvanced_workspaceSize( static void* ZSTD_rust_createCDictAdvanced_allocate( void* context, size_t workspaceSize) { - return ZSTD_customMalloc(workspaceSize, *(const ZSTD_customMem*)context); + ZSTD_rust_createCDictAdvancedContext const* const createContext = + (const ZSTD_rust_createCDictAdvancedContext*)context; + return ZSTD_customMalloc(workspaceSize, createContext->customMem); } -static void* ZSTD_rust_createCDictAdvanced_create( - void* context, void* workspace, size_t workspaceSize, - size_t dictSize, int dictLoadMethod, - const ZSTD_compressionParameters* cParams, - int useRowMatchFinder, int enableDedicatedDictSearch) +static void ZSTD_rust_createCDictAdvanced_createWorkspace( + void* context, void* workspace, size_t workspaceSize) { - ZSTD_customMem const customMem = *(const ZSTD_customMem*)context; - ZSTD_cwksp ws; - ZSTD_CDict* cdict; - - (void)dictSize; - (void)dictLoadMethod; - (void)cParams; - (void)enableDedicatedDictSearch; + ZSTD_rust_createCDictAdvancedContext* const createContext = + (ZSTD_rust_createCDictAdvancedContext*)context; DEBUGLOG(3, "ZSTD_createCDict_advanced_internal (workspaceSize=%u)", (unsigned)workspaceSize); - if (workspace == NULL) return NULL; + ZSTD_cwksp_init(&createContext->workspace, workspace, workspaceSize, + ZSTD_cwksp_dynamic_alloc); +} - ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc); - cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); - if (cdict == NULL) return NULL; - ZSTD_cwksp_move(&cdict->workspace, &ws); - cdict->customMem = customMem; - cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ - cdict->useRowMatchFinder = (ZSTD_ParamSwitch_e)useRowMatchFinder; - return cdict; +static void* ZSTD_rust_createCDictAdvanced_reserveObject(void* context) +{ + ZSTD_rust_createCDictAdvancedContext* const createContext = + (ZSTD_rust_createCDictAdvancedContext*)context; + return ZSTD_cwksp_reserve_object(&createContext->workspace, sizeof(ZSTD_CDict)); +} + +static void ZSTD_rust_createCDictAdvanced_moveWorkspace( + void* context, void* cdict) +{ + ZSTD_rust_createCDictAdvancedContext* const createContext = + (ZSTD_rust_createCDictAdvancedContext*)context; + ZSTD_cwksp_move(&((ZSTD_CDict*)cdict)->workspace, &createContext->workspace); +} + +static void ZSTD_rust_createCDictAdvanced_initialize( + void* context, void* cdict, int useRowMatchFinder) +{ + ZSTD_rust_createCDictAdvancedContext const* const createContext = + (const ZSTD_rust_createCDictAdvancedContext*)context; + ZSTD_CDict* const dictionary = (ZSTD_CDict*)cdict; + dictionary->customMem = createContext->customMem; + dictionary->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ + dictionary->useRowMatchFinder = (ZSTD_ParamSwitch_e)useRowMatchFinder; } static void ZSTD_rust_createCDictAdvanced_freeWorkspace( void* context, void* workspace) { - ZSTD_customFree(workspace, *(const ZSTD_customMem*)context); -} - -ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams, - 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_createCDictAdvancedContext const* const createContext = + (const ZSTD_rust_createCDictAdvancedContext*)context; + ZSTD_customFree(workspace, createContext->customMem); } static size_t ZSTD_rust_createCDictAdvanced_init( @@ -6814,6 +6847,24 @@ static void ZSTD_rust_createCDictAdvanced_free(void* context, void* cdict) ZSTD_freeCDict((ZSTD_CDict*)cdict); } +ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + 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_CDict* ZSTD_createCDict_advanced2( const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, @@ -6822,13 +6873,15 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( ZSTD_customMem customMem) { ZSTD_CCtx_params cctxParams; + ZSTD_rust_createCDictAdvancedContext context; ZSTD_rust_createCDictAdvancedState state; DEBUGLOG(3, "ZSTD_createCDict_advanced2, dictSize=%u, mode=%u", (unsigned)dictSize, (unsigned)dictContentType); if (originalCctxParams == NULL) return NULL; cctxParams = *originalCctxParams; - state.callbackContext = &customMem; + context.customMem = customMem; + state.callbackContext = &context; state.cctxParams = &cctxParams; state.cParams = &cctxParams.cParams; state.enableDedicatedDictSearch = &cctxParams.enableDedicatedDictSearch; @@ -6838,7 +6891,10 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( state.validateCustomMem = ZSTD_rust_createCDictAdvanced_validateCustomMem; state.workspaceSize = ZSTD_rust_createCDictAdvanced_workspaceSize; state.allocate = ZSTD_rust_createCDictAdvanced_allocate; - state.create = ZSTD_rust_createCDictAdvanced_create; + state.createWorkspace = ZSTD_rust_createCDictAdvanced_createWorkspace; + state.reserveObject = ZSTD_rust_createCDictAdvanced_reserveObject; + state.moveWorkspace = ZSTD_rust_createCDictAdvanced_moveWorkspace; + state.initialize = ZSTD_rust_createCDictAdvanced_initialize; state.init = ZSTD_rust_createCDictAdvanced_init; state.freeWorkspace = ZSTD_rust_createCDictAdvanced_freeWorkspace; state.free = ZSTD_rust_createCDictAdvanced_free; @@ -6847,6 +6903,10 @@ ZSTD_CDict* ZSTD_createCDict_advanced2( (int)dictLoadMethod, (int)dictContentType); } +/* The implementation above intentionally keeps the private workspace and + * object operations in C. Rust only sequences those operations and handles + * the public construction policy. */ + static void* ZSTD_rust_createCDict_create( void* context, const void* dict, size_t dictSize, int dictLoadMethod, int dictContentType, @@ -6936,35 +6996,56 @@ typedef struct { ZSTD_dictContentType_e dictContentType; ZSTD_compressionParameters cParams; ZSTD_ParamSwitch_e useRowMatchFinder; + ZSTD_cwksp workspaceState; + ZSTD_CCtx_params params; } ZSTD_rust_initStaticCDictContext; -static void* ZSTD_rust_initStaticCDict_init(void* opaque) +static void ZSTD_rust_initStaticCDict_createWorkspace(void* opaque) { ZSTD_rust_initStaticCDictContext* const context = (ZSTD_rust_initStaticCDictContext*)opaque; - ZSTD_cwksp ws; - ZSTD_CDict* cdict; - ZSTD_CCtx_params params; - - ZSTD_cwksp_init(&ws, context->workspace, context->workspaceSize, + ZSTD_cwksp_init(&context->workspaceState, context->workspace, context->workspaceSize, ZSTD_cwksp_static_alloc); - cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); - if (cdict == NULL) return NULL; - ZSTD_cwksp_move(&cdict->workspace, &ws); +} - ZSTD_CCtxParams_init(¶ms, 0); - params.cParams = context->cParams; - params.useRowMatchFinder = context->useRowMatchFinder; - cdict->useRowMatchFinder = context->useRowMatchFinder; - cdict->compressionLevel = ZSTD_NO_CLEVEL; +static void* ZSTD_rust_initStaticCDict_reserveObject(void* opaque) +{ + ZSTD_rust_initStaticCDictContext* const context = + (ZSTD_rust_initStaticCDictContext*)opaque; + return ZSTD_cwksp_reserve_object(&context->workspaceState, sizeof(ZSTD_CDict)); +} - if (ZSTD_isError( ZSTD_initCDict_internal(cdict, - context->dict, context->dictSize, - context->dictLoadMethod, - context->dictContentType, - params) )) +static void ZSTD_rust_initStaticCDict_moveWorkspace( + void* opaque, void* cdict) +{ + ZSTD_rust_initStaticCDictContext* const context = + (ZSTD_rust_initStaticCDictContext*)opaque; + ZSTD_cwksp_move(&((ZSTD_CDict*)cdict)->workspace, &context->workspaceState); +} + +static void ZSTD_rust_initStaticCDict_initialize(void* opaque, void* cdict) +{ + ZSTD_rust_initStaticCDictContext* const context = + (ZSTD_rust_initStaticCDictContext*)opaque; + ZSTD_CDict* const dictionary = (ZSTD_CDict*)cdict; + ZSTD_CCtx_params* const params = &context->params; + + ZSTD_CCtxParams_init(params, 0); + params->cParams = context->cParams; + params->useRowMatchFinder = context->useRowMatchFinder; + dictionary->useRowMatchFinder = context->useRowMatchFinder; + dictionary->compressionLevel = ZSTD_NO_CLEVEL; +} + +static void* ZSTD_rust_initStaticCDict_init(void* opaque, void* cdict) +{ + ZSTD_rust_initStaticCDictContext const* const context = + (const ZSTD_rust_initStaticCDictContext*)opaque; + if (ZSTD_isError( ZSTD_initCDict_internal( + (ZSTD_CDict*)cdict, context->dict, context->dictSize, + context->dictLoadMethod, context->dictContentType, + context->params) )) return NULL; - return cdict; } @@ -7005,6 +7086,10 @@ const ZSTD_CDict* ZSTD_initStaticCDict( state.workspace = workspace; state.workspaceSize = workspaceSize; state.neededSize = neededSize; + state.createWorkspace = ZSTD_rust_initStaticCDict_createWorkspace; + state.reserveObject = ZSTD_rust_initStaticCDict_reserveObject; + state.moveWorkspace = ZSTD_rust_initStaticCDict_moveWorkspace; + state.initialize = ZSTD_rust_initStaticCDict_initialize; state.init = ZSTD_rust_initStaticCDict_init; return (const ZSTD_CDict*)ZSTD_rust_initStaticCDict(&state); } diff --git a/rust/src/zstd_compress_dictionary.rs b/rust/src/zstd_compress_dictionary.rs index ac5d10115..fec8140cc 100644 --- a/rust/src/zstd_compress_dictionary.rs +++ b/rust/src/zstd_compress_dictionary.rs @@ -835,16 +835,10 @@ type CreateCDictAdvancedWorkspaceSizeFn = unsafe extern "C" fn( c_int, ) -> usize; type CreateCDictAdvancedAllocateFn = unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void; -type CreateCDictAdvancedCreateFn = unsafe extern "C" fn( - *mut c_void, - *mut c_void, - usize, - usize, - c_int, - *const ZSTD_compressionParameters, - c_int, - c_int, -) -> *mut c_void; +type CreateCDictAdvancedCreateWorkspaceFn = unsafe extern "C" fn(*mut c_void, *mut c_void, usize); +type CreateCDictAdvancedReserveObjectFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void; +type CreateCDictAdvancedMoveWorkspaceFn = unsafe extern "C" fn(*mut c_void, *mut c_void); +type CreateCDictAdvancedInitializeFn = unsafe extern "C" fn(*mut c_void, *mut c_void, c_int); type CreateCDictAdvancedInitFn = unsafe extern "C" fn( *mut c_void, *mut c_void, @@ -877,7 +871,10 @@ pub struct ZSTD_rust_createCDictAdvancedState { validate_custom_mem: CreateCDictAdvancedValidateCustomMemFn, workspace_size: CreateCDictAdvancedWorkspaceSizeFn, allocate: CreateCDictAdvancedAllocateFn, - create: CreateCDictAdvancedCreateFn, + create_workspace: CreateCDictAdvancedCreateWorkspaceFn, + reserve_object: CreateCDictAdvancedReserveObjectFn, + move_workspace: CreateCDictAdvancedMoveWorkspaceFn, + initialize: CreateCDictAdvancedInitializeFn, init: CreateCDictAdvancedInitFn, free_workspace: CreateCDictAdvancedFreeWorkspaceFn, free: CreateCDictAdvancedFreeFn, @@ -917,28 +914,41 @@ const _: () = { == size_of::<[usize; 7]>() + size_of::<[u32; 2]>() ); assert!( - offset_of!(ZSTD_rust_createCDictAdvancedState, create) + offset_of!(ZSTD_rust_createCDictAdvancedState, create_workspace) == size_of::<[usize; 8]>() + size_of::<[u32; 2]>() ); assert!( - offset_of!(ZSTD_rust_createCDictAdvancedState, init) + offset_of!(ZSTD_rust_createCDictAdvancedState, reserve_object) == size_of::<[usize; 9]>() + size_of::<[u32; 2]>() ); assert!( - offset_of!(ZSTD_rust_createCDictAdvancedState, free_workspace) + offset_of!(ZSTD_rust_createCDictAdvancedState, move_workspace) == size_of::<[usize; 10]>() + size_of::<[u32; 2]>() ); assert!( - offset_of!(ZSTD_rust_createCDictAdvancedState, free) + offset_of!(ZSTD_rust_createCDictAdvancedState, initialize) == size_of::<[usize; 11]>() + size_of::<[u32; 2]>() ); assert!( - size_of::() + offset_of!(ZSTD_rust_createCDictAdvancedState, init) == size_of::<[usize; 12]>() + size_of::<[u32; 2]>() ); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedState, free_workspace) + == size_of::<[usize; 13]>() + size_of::<[u32; 2]>() + ); + assert!( + offset_of!(ZSTD_rust_createCDictAdvancedState, free) + == size_of::<[usize; 14]>() + size_of::<[u32; 2]>() + ); + assert!( + size_of::() + == size_of::<[usize; 15]>() + size_of::<[u32; 2]>() + ); }; -/// Prepare advanced-CDict parameters and run the C-owned construction path. +/// Prepare advanced-CDict parameters and run the C-owned construction leaves +/// in their original allocation, workspace, and initialization order. #[no_mangle] pub unsafe extern "C" fn ZSTD_rust_createCDictAdvanced( state: *const ZSTD_rust_createCDictAdvancedState, @@ -991,23 +1001,20 @@ pub unsafe extern "C" fn ZSTD_rust_createCDictAdvanced( return ptr::null_mut(); } - let cdict = unsafe { - (state.create)( - state.callback_context, - workspace, - workspace_size, - dict_size, - dict_load_method, - state.cparams, - *state.use_row_match_finder, - *state.enable_dedicated_dict_search, - ) - }; + unsafe { + (state.create_workspace)(state.callback_context, workspace, workspace_size); + } + let cdict = unsafe { (state.reserve_object)(state.callback_context) }; if cdict.is_null() { unsafe { (state.free_workspace)(state.callback_context, workspace) }; return ptr::null_mut(); } + unsafe { + (state.move_workspace)(state.callback_context, cdict); + (state.initialize)(state.callback_context, cdict, *state.use_row_match_finder); + } + let init_result = unsafe { (state.init)( state.callback_context, @@ -1068,19 +1075,27 @@ pub unsafe extern "C" fn ZSTD_rust_freeCDict(state: *const ZSTD_rust_freeCDictSt 0 } -type InitStaticCDictFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void; +type InitStaticCDictCreateWorkspaceFn = unsafe extern "C" fn(*mut c_void); +type InitStaticCDictReserveObjectFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void; +type InitStaticCDictMoveWorkspaceFn = unsafe extern "C" fn(*mut c_void, *mut c_void); +type InitStaticCDictInitializeFn = unsafe extern "C" fn(*mut c_void, *mut c_void); +type InitStaticCDictFn = unsafe extern "C" fn(*mut c_void, *mut c_void) -> *mut c_void; /// Explicit projection for the public `ZSTD_initStaticCDict` wrapper. /// /// Rust owns workspace pointer/alignment validation, minimum-size validation, /// and callback ordering. C retains the private static-workspace layout and -/// dictionary initialization behind one callback. +/// dictionary initialization behind narrow callbacks. #[repr(C)] pub struct ZSTD_rust_initStaticCDictState { callback_context: *mut c_void, workspace: *mut c_void, workspace_size: usize, needed_size: usize, + create_workspace: InitStaticCDictCreateWorkspaceFn, + reserve_object: InitStaticCDictReserveObjectFn, + move_workspace: InitStaticCDictMoveWorkspaceFn, + initialize: InitStaticCDictInitializeFn, init: InitStaticCDictFn, } @@ -1089,8 +1104,12 @@ const _: () = { assert!(offset_of!(ZSTD_rust_initStaticCDictState, workspace) == size_of::()); assert!(offset_of!(ZSTD_rust_initStaticCDictState, workspace_size) == 2 * size_of::()); assert!(offset_of!(ZSTD_rust_initStaticCDictState, needed_size) == 3 * size_of::()); - assert!(offset_of!(ZSTD_rust_initStaticCDictState, init) == 4 * size_of::()); - assert!(size_of::() == size_of::<[usize; 5]>()); + assert!(offset_of!(ZSTD_rust_initStaticCDictState, create_workspace) == 4 * size_of::()); + assert!(offset_of!(ZSTD_rust_initStaticCDictState, reserve_object) == 5 * size_of::()); + assert!(offset_of!(ZSTD_rust_initStaticCDictState, move_workspace) == 6 * size_of::()); + assert!(offset_of!(ZSTD_rust_initStaticCDictState, initialize) == 7 * size_of::()); + assert!(offset_of!(ZSTD_rust_initStaticCDictState, init) == usize::BITS as usize); + assert!(size_of::() == size_of::<[usize; 9]>()); }; /// Validate static CDict workspace ownership before entering the C leaf. @@ -1109,7 +1128,18 @@ pub unsafe extern "C" fn ZSTD_rust_initStaticCDict( { return ptr::null_mut(); } - unsafe { (state.init)(state.callback_context) } + unsafe { + (state.create_workspace)(state.callback_context); + } + let cdict = unsafe { (state.reserve_object)(state.callback_context) }; + if cdict.is_null() { + return ptr::null_mut(); + } + unsafe { + (state.move_workspace)(state.callback_context, cdict); + (state.initialize)(state.callback_context, cdict); + (state.init)(state.callback_context, cdict) + } } type CompressBeginUsingDictBeginFn = @@ -4587,13 +4617,12 @@ mod tests { workspace_size_enable_dedicated_dict_search: c_int, allocated_workspace: *mut c_void, allocated_workspace_size: usize, - create_workspace: *mut c_void, - create_workspace_size: usize, - create_dict_size: usize, - create_dict_load_method: c_int, - cparams: *const ZSTD_compressionParameters, + created_workspace: *mut c_void, + created_workspace_size: usize, + reserved_cdict: *mut c_void, + moved_cdict: *mut c_void, + initialized_cdict: *mut c_void, use_row_match_finder: c_int, - enable_dedicated_dict_search: c_int, cdict_result: *mut c_void, init_cdict: *mut c_void, init_dict: *const c_void, @@ -4642,28 +4671,46 @@ mod tests { probe.allocated_workspace } - unsafe extern "C" fn create_cdict_advanced_test_create( + unsafe extern "C" fn create_cdict_advanced_test_create_workspace( context: *mut c_void, workspace: *mut c_void, workspace_size: usize, - dict_size: usize, - dict_load_method: c_int, - cparams: *const ZSTD_compressionParameters, - use_row_match_finder: c_int, - enable_dedicated_dict_search: c_int, + ) { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("create_workspace"); + probe.created_workspace = workspace; + probe.created_workspace_size = workspace_size; + } + + unsafe extern "C" fn create_cdict_advanced_test_reserve_object( + context: *mut c_void, ) -> *mut c_void { let probe = unsafe { &mut *context.cast::() }; - probe.events.push("create"); - probe.create_workspace = workspace; - probe.create_workspace_size = workspace_size; - probe.create_dict_size = dict_size; - probe.create_dict_load_method = dict_load_method; - probe.cparams = cparams; - probe.use_row_match_finder = use_row_match_finder; - probe.enable_dedicated_dict_search = enable_dedicated_dict_search; + probe.events.push("reserve_object"); + probe.reserved_cdict = probe.cdict_result; probe.cdict_result } + unsafe extern "C" fn create_cdict_advanced_test_move_workspace( + context: *mut c_void, + cdict: *mut c_void, + ) { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("move_workspace"); + probe.moved_cdict = cdict; + } + + unsafe extern "C" fn create_cdict_advanced_test_initialize( + context: *mut c_void, + cdict: *mut c_void, + use_row_match_finder: c_int, + ) { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("initialize"); + probe.initialized_cdict = cdict; + probe.use_row_match_finder = use_row_match_finder; + } + unsafe extern "C" fn create_cdict_advanced_test_init( context: *mut c_void, cdict: *mut c_void, @@ -4731,7 +4778,10 @@ mod tests { validate_custom_mem: create_cdict_advanced_test_validate_custom_mem, workspace_size: create_cdict_advanced_test_workspace_size, allocate: create_cdict_advanced_test_allocate, - create: create_cdict_advanced_test_create, + create_workspace: create_cdict_advanced_test_create_workspace, + reserve_object: create_cdict_advanced_test_reserve_object, + move_workspace: create_cdict_advanced_test_move_workspace, + initialize: create_cdict_advanced_test_initialize, init: create_cdict_advanced_test_init, free_workspace: create_cdict_advanced_test_free_workspace, free: create_cdict_advanced_test_free, @@ -4782,7 +4832,16 @@ mod tests { assert_eq!(result, probe.cdict_result); assert_eq!( probe.events, - ["validate", "workspace_size", "allocate", "create", "init"] + [ + "validate", + "workspace_size", + "allocate", + "create_workspace", + "reserve_object", + "move_workspace", + "initialize", + "init" + ] ); assert_eq!(probe.workspace_size_dict_size, dict.len()); assert_eq!(probe.workspace_size_dict_load_method, ZSTD_DLM_BY_REF); @@ -4796,16 +4855,12 @@ mod tests { enable_dedicated_dict_search ); assert_eq!(probe.allocated_workspace_size, 123); - assert_eq!(probe.create_workspace, probe.allocated_workspace); - assert_eq!(probe.create_workspace_size, 123); - assert_eq!(probe.create_dict_size, dict.len()); - assert_eq!(probe.create_dict_load_method, ZSTD_DLM_BY_REF); - assert_eq!(probe.cparams, &cparams); + assert_eq!(probe.created_workspace, probe.allocated_workspace); + assert_eq!(probe.created_workspace_size, 123); + assert_eq!(probe.reserved_cdict, probe.cdict_result); + assert_eq!(probe.moved_cdict, probe.cdict_result); + assert_eq!(probe.initialized_cdict, probe.cdict_result); assert_eq!(probe.use_row_match_finder, use_row_match_finder); - assert_eq!( - probe.enable_dedicated_dict_search, - enable_dedicated_dict_search - ); assert_eq!(probe.init_cdict, probe.cdict_result); assert_eq!(probe.init_dict, dict.as_ptr().cast()); assert_eq!(probe.init_dict_size, dict.len()); @@ -4838,7 +4893,7 @@ mod tests { assert!(result.is_null()); assert_eq!(probe.events, ["validate"]); - assert!(probe.create_workspace.is_null()); + assert!(probe.created_workspace.is_null()); assert!(probe.free_workspace.is_null()); assert!(probe.free_cdict.is_null()); } @@ -4870,13 +4925,13 @@ mod tests { assert!(result.is_null()); assert_eq!(probe.events, ["validate", "workspace_size", "allocate"]); assert_eq!(probe.allocated_workspace_size, 321); - assert!(probe.create_workspace.is_null()); + assert!(probe.created_workspace.is_null()); assert!(probe.free_workspace.is_null()); assert!(probe.free_cdict.is_null()); } #[test] - fn create_cdict_advanced_frees_workspace_after_creation_failure() { + fn create_cdict_advanced_frees_workspace_after_reservation_failure() { let workspace = ptr::dangling_mut::(); let mut probe = CreateCDictAdvancedProbe { custom_mem_valid: 1, @@ -4908,13 +4963,13 @@ mod tests { "validate", "workspace_size", "allocate", - "create", + "create_workspace", + "reserve_object", "free_workspace" ] ); - assert_eq!(probe.create_workspace, workspace); - assert_eq!(probe.create_workspace_size, 321); - assert_eq!(probe.create_dict_size, 0); + assert_eq!(probe.created_workspace, workspace); + assert_eq!(probe.created_workspace_size, 321); assert_eq!(probe.free_workspace, workspace); assert!(probe.free_cdict.is_null()); } @@ -4955,14 +5010,19 @@ mod tests { "validate", "workspace_size", "allocate", - "create", + "create_workspace", + "reserve_object", + "move_workspace", + "initialize", "init", "free" ] ); - assert_eq!(probe.create_workspace, workspace); - assert_eq!(probe.create_workspace_size, 321); - assert_eq!(probe.create_dict_size, 0); + assert_eq!(probe.created_workspace, workspace); + assert_eq!(probe.created_workspace_size, 321); + assert_eq!(probe.reserved_cdict, cdict); + assert_eq!(probe.moved_cdict, cdict); + assert_eq!(probe.initialized_cdict, cdict); assert!(probe.free_workspace.is_null()); assert_eq!(probe.free_cdict, cdict); } @@ -5033,12 +5093,53 @@ mod tests { #[derive(Default)] struct InitStaticCDictProbe { events: Vec<&'static str>, + reserved_cdict: *mut c_void, + moved_cdict: *mut c_void, + initialized_cdict: *mut c_void, + init_cdict: *mut c_void, + initialized: bool, result: *mut c_void, } - unsafe extern "C" fn init_static_cdict_test_init(context: *mut c_void) -> *mut c_void { + unsafe extern "C" fn init_static_cdict_test_create_workspace(context: *mut c_void) { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("create_workspace"); + } + + unsafe extern "C" fn init_static_cdict_test_reserve_object( + context: *mut c_void, + ) -> *mut c_void { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("reserve_object"); + probe.reserved_cdict + } + + unsafe extern "C" fn init_static_cdict_test_move_workspace( + context: *mut c_void, + cdict: *mut c_void, + ) { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("move_workspace"); + probe.moved_cdict = cdict; + } + + unsafe extern "C" fn init_static_cdict_test_initialize( + context: *mut c_void, + cdict: *mut c_void, + ) { + let probe = unsafe { &mut *context.cast::() }; + probe.events.push("initialize"); + probe.initialized_cdict = cdict; + probe.initialized = true; + } + + unsafe extern "C" fn init_static_cdict_test_init( + context: *mut c_void, + cdict: *mut c_void, + ) -> *mut c_void { let probe = unsafe { &mut *context.cast::() }; probe.events.push("init"); + probe.init_cdict = cdict; probe.result } @@ -5053,6 +5154,10 @@ mod tests { workspace, workspace_size, needed_size, + create_workspace: init_static_cdict_test_create_workspace, + reserve_object: init_static_cdict_test_reserve_object, + move_workspace: init_static_cdict_test_move_workspace, + initialize: init_static_cdict_test_initialize, init: init_static_cdict_test_init, } } @@ -5095,7 +5200,9 @@ mod tests { #[test] fn init_static_cdict_calls_the_initializer_after_workspace_validation() { + let cdict = ptr::dangling_mut::(); let mut probe = InitStaticCDictProbe { + reserved_cdict: cdict, result: ptr::dangling_mut(), ..Default::default() }; @@ -5110,7 +5217,72 @@ mod tests { let result = unsafe { ZSTD_rust_initStaticCDict(&state) }; assert_eq!(result, probe.result); - assert_eq!(probe.events, ["init"]); + assert_eq!( + probe.events, + [ + "create_workspace", + "reserve_object", + "move_workspace", + "initialize", + "init" + ] + ); + assert_eq!(probe.moved_cdict, cdict); + assert_eq!(probe.initialized_cdict, cdict); + assert_eq!(probe.init_cdict, cdict); + assert!(probe.initialized); + } + + #[test] + fn init_static_cdict_stops_after_object_reservation_failure() { + let mut probe = InitStaticCDictProbe::default(); + let mut workspace = [0usize; 1]; + let state = init_static_cdict_test_state( + &mut probe, + workspace.as_mut_ptr().cast(), + size_of_val(&workspace), + 0, + ); + + let result = unsafe { ZSTD_rust_initStaticCDict(&state) }; + + assert!(result.is_null()); + assert_eq!(probe.events, ["create_workspace", "reserve_object"]); + assert!(probe.moved_cdict.is_null()); + assert!(!probe.initialized); + } + + #[test] + fn init_static_cdict_propagates_initializer_failure_after_setup() { + let cdict = ptr::dangling_mut::(); + let mut probe = InitStaticCDictProbe { + reserved_cdict: cdict, + result: ptr::null_mut(), + ..Default::default() + }; + let mut workspace = [0usize; 1]; + let state = init_static_cdict_test_state( + &mut probe, + workspace.as_mut_ptr().cast(), + size_of_val(&workspace), + size_of_val(&workspace), + ); + + let result = unsafe { ZSTD_rust_initStaticCDict(&state) }; + + assert!(result.is_null()); + assert_eq!(probe.init_cdict, cdict); + assert!(probe.initialized); + assert_eq!( + probe.events, + [ + "create_workspace", + "reserve_object", + "move_workspace", + "initialize", + "init" + ] + ); } #[test]