diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e262d77f0..48de39601 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2497,7 +2497,8 @@ typedef struct { ZSTD_rust_resetCCtxByCopyingCDictMarkTables_f markTablesClean; ZSTD_rust_resetCCtxByCopyingCDictState_f copyMatchState; ZSTD_rust_resetCCtxByCopyingCDictState_f copyDictState; - ZSTD_rust_resetCCtxByCopyingCDictState_f copyBlockState; + ZSTD_compressedBlockState_t** destinationBlockState; + const ZSTD_compressedBlockState_t* sourceBlockState; int zbuff; } ZSTD_rust_resetCCtxByCopyingCDictState; size_t ZSTD_rust_resetCCtxByCopyingCDict( @@ -2513,7 +2514,7 @@ typedef char ZSTD_rust_reset_cctx_by_copying_cdict_state_layout[ && offsetof(ZSTD_rust_resetCCtxByCopyingCDictState, reset) == 3 * sizeof(void*) + sizeof(U64) && offsetof(ZSTD_rust_resetCCtxByCopyingCDictState, zbuff) - == 3 * sizeof(void*) + sizeof(U64) + 8 * sizeof(void*) + == 3 * sizeof(void*) + sizeof(U64) + 9 * sizeof(void*) && sizeof(ZSTD_rust_resetCCtxByCopyingCDictState) == ((offsetof(ZSTD_rust_resetCCtxByCopyingCDictState, zbuff) + sizeof(int) + sizeof(void*) - 1) / sizeof(void*)) @@ -2534,7 +2535,8 @@ typedef struct { ZSTD_rust_resetCCtxByAttachingCDictReset_f reset; ZSTD_rust_resetCCtxByAttachingCDictAttach_f attach; ZSTD_rust_resetCCtxByAttachingCDictState_f copyDictState; - ZSTD_rust_resetCCtxByAttachingCDictState_f copyBlockState; + ZSTD_compressedBlockState_t** destinationBlockState; + const ZSTD_compressedBlockState_t* sourceBlockState; int zbuff; } ZSTD_rust_resetCCtxByAttachingCDictState; size_t ZSTD_rust_resetCCtxByAttachingCDict( @@ -2550,7 +2552,7 @@ typedef char ZSTD_rust_reset_cctx_by_attaching_cdict_state_layout[ && offsetof(ZSTD_rust_resetCCtxByAttachingCDictState, reset) == 3 * sizeof(void*) + sizeof(U64) && offsetof(ZSTD_rust_resetCCtxByAttachingCDictState, zbuff) - == 3 * sizeof(void*) + sizeof(U64) + 4 * sizeof(void*) + == 3 * sizeof(void*) + sizeof(U64) + 5 * sizeof(void*) && sizeof(ZSTD_rust_resetCCtxByAttachingCDictState) == ((offsetof(ZSTD_rust_resetCCtxByAttachingCDictState, zbuff) + sizeof(int) + sizeof(void*) - 1) / sizeof(void*)) @@ -4518,15 +4520,6 @@ static void ZSTD_rust_resetCCtx_byAttachingCDict_copy_dict_state( cctx->dictContentSize = cdict->dictContentSize; } -static void ZSTD_rust_resetCCtx_byAttachingCDict_copy_block_state( - void* context, const void* cdictOpaque) -{ - ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; - const ZSTD_CDict* const cdict = (const ZSTD_CDict*)cdictOpaque; - ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, - sizeof(cdict->cBlockState)); -} - static size_t ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, @@ -4542,7 +4535,8 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, state.reset = ZSTD_rust_resetCCtx_byAttachingCDict_reset; state.attach = ZSTD_rust_resetCCtx_byAttachingCDict_attach; state.copyDictState = ZSTD_rust_resetCCtx_byAttachingCDict_copy_dict_state; - state.copyBlockState = ZSTD_rust_resetCCtx_byAttachingCDict_copy_block_state; + state.destinationBlockState = &cctx->blockState.prevCBlock; + state.sourceBlockState = &cdict->cBlockState; state.zbuff = (int)zbuff; return ZSTD_rust_resetCCtxByAttachingCDict(&state); } @@ -4667,15 +4661,6 @@ static void ZSTD_rust_resetCCtx_byCopyingCDict_copy_dict_state( cctx->dictContentSize = cdict->dictContentSize; } -static void ZSTD_rust_resetCCtx_byCopyingCDict_copy_block_state( - void* context, const void* cdictOpaque) -{ - ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; - const ZSTD_CDict* const cdict = (const ZSTD_CDict*)cdictOpaque; - ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, - sizeof(cdict->cBlockState)); -} - static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict, ZSTD_CCtx_params params, @@ -4699,8 +4684,8 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, ZSTD_rust_resetCCtx_byCopyingCDict_copy_match_state; state.copyDictState = ZSTD_rust_resetCCtx_byCopyingCDict_copy_dict_state; - state.copyBlockState = - ZSTD_rust_resetCCtx_byCopyingCDict_copy_block_state; + state.destinationBlockState = &cctx->blockState.prevCBlock; + state.sourceBlockState = &cdict->cBlockState; state.zbuff = (int)zbuff; return ZSTD_rust_resetCCtxByCopyingCDict(&state); } diff --git a/rust/src/zstd_compress_dictionary.rs b/rust/src/zstd_compress_dictionary.rs index a9c73f824..f759f9d2b 100644 --- a/rust/src/zstd_compress_dictionary.rs +++ b/rust/src/zstd_compress_dictionary.rs @@ -1152,7 +1152,7 @@ pub unsafe extern "C" fn ZSTD_rust_compressBegin( || cdict_compression_level == 0) && unsafe { *state.attach_dict_pref } != unsafe { *state.force_load }; if should_attach { - return unsafe { + let result = unsafe { reset_using_cdict( state.callback_context, state.cdict, @@ -1161,6 +1161,7 @@ pub unsafe extern "C" fn ZSTD_rust_compressBegin( *state.zbuff, ) }; + return result; } let reset_result = unsafe { @@ -1321,7 +1322,8 @@ pub struct ZSTD_rust_resetCCtxByCopyingCDictState { mark_tables_clean: Option, copy_match_state: Option, copy_dict_state: Option, - copy_block_state: Option, + destination_block_state: *mut *mut ZSTD_compressedBlockState_t, + source_block_state: *const ZSTD_compressedBlockState_t, zbuff: c_int, } @@ -1342,7 +1344,7 @@ const _: () = { ); assert!( offset_of!(ZSTD_rust_resetCCtxByCopyingCDictState, zbuff) - == 3 * size_of::() + size_of::() + size_of::<[usize; 8]>() + == 3 * size_of::() + size_of::() + size_of::<[usize; 9]>() ); assert!( size_of::() @@ -1352,7 +1354,8 @@ const _: () = { ); }; -/// Run the private CDict-copy operation through C-owned layout callbacks. +/// Run the private CDict-copy operation through C-owned layout callbacks and +/// copy the compressed-block state directly in Rust. #[no_mangle] pub unsafe extern "C" fn ZSTD_rust_resetCCtxByCopyingCDict( state: *const ZSTD_rust_resetCCtxByCopyingCDictState, @@ -1369,7 +1372,6 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxByCopyingCDict( Some(mark_tables_clean), Some(copy_match_state), Some(copy_dict_state), - Some(copy_block_state), ) = ( state.reset, state.mark_tables_dirty, @@ -1378,12 +1380,16 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxByCopyingCDict( state.mark_tables_clean, state.copy_match_state, state.copy_dict_state, - state.copy_block_state, ) else { return ERROR(ZstdErrorCode::Generic); }; - if state.callback_context.is_null() || state.cdict.is_null() || state.params.is_null() { + if state.callback_context.is_null() + || state.cdict.is_null() + || state.params.is_null() + || state.destination_block_state.is_null() + || state.source_block_state.is_null() + { return ERROR(ZstdErrorCode::Generic); } @@ -1404,7 +1410,11 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxByCopyingCDict( mark_tables_clean(state.callback_context); copy_match_state(state.callback_context, state.cdict); copy_dict_state(state.callback_context, state.cdict); - copy_block_state(state.callback_context, state.cdict); + let destination_block_state = *state.destination_block_state; + if destination_block_state.is_null() { + return ERROR(ZstdErrorCode::Generic); + } + ptr::copy_nonoverlapping(state.source_block_state, destination_block_state, 1); } 0 } @@ -1427,7 +1437,8 @@ pub struct ZSTD_rust_resetCCtxByAttachingCDictState { reset: Option, attach: Option, copy_dict_state: Option, - copy_block_state: Option, + destination_block_state: *mut *mut ZSTD_compressedBlockState_t, + source_block_state: *const ZSTD_compressedBlockState_t, zbuff: c_int, } @@ -1448,7 +1459,7 @@ const _: () = { ); assert!( offset_of!(ZSTD_rust_resetCCtxByAttachingCDictState, zbuff) - == 3 * size_of::() + size_of::() + size_of::<[usize; 4]>() + == 3 * size_of::() + size_of::() + size_of::<[usize; 5]>() ); assert!( size_of::() @@ -1458,7 +1469,8 @@ const _: () = { ); }; -/// Run the private CDict-attachment operation through C-owned layout callbacks. +/// Run the private CDict-attachment operation through C-owned layout callbacks +/// and copy the compressed-block state directly in Rust. #[no_mangle] pub unsafe extern "C" fn ZSTD_rust_resetCCtxByAttachingCDict( state: *const ZSTD_rust_resetCCtxByAttachingCDictState, @@ -1467,15 +1479,17 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxByAttachingCDict( return ERROR(ZstdErrorCode::Generic); } let state = unsafe { &*state }; - let (Some(reset), Some(attach), Some(copy_dict_state), Some(copy_block_state)) = ( - state.reset, - state.attach, - state.copy_dict_state, - state.copy_block_state, - ) else { + let (Some(reset), Some(attach), Some(copy_dict_state)) = + (state.reset, state.attach, state.copy_dict_state) + else { return ERROR(ZstdErrorCode::Generic); }; - if state.callback_context.is_null() || state.cdict.is_null() || state.params.is_null() { + if state.callback_context.is_null() + || state.cdict.is_null() + || state.params.is_null() + || state.destination_block_state.is_null() + || state.source_block_state.is_null() + { return ERROR(ZstdErrorCode::Generic); } @@ -1492,7 +1506,11 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxByAttachingCDict( } attach(state.callback_context, state.cdict); copy_dict_state(state.callback_context, state.cdict); - copy_block_state(state.callback_context, state.cdict); + let destination_block_state = *state.destination_block_state; + if destination_block_state.is_null() { + return ERROR(ZstdErrorCode::Generic); + } + ptr::copy_nonoverlapping(state.source_block_state, destination_block_state, 1); } 0 } @@ -2766,19 +2784,12 @@ mod tests { .push("dict"); } - unsafe extern "C" fn reset_cctx_by_copying_cdict_copy_block_state( - context: *mut c_void, - _cdict: *const c_void, - ) { - unsafe { reset_cctx_by_copying_cdict_probe(context) } - .events - .push("block"); - } - fn reset_cctx_by_copying_cdict_test_state( probe: &mut ResetCCtxByCopyingCDictProbe, cdict: *const c_void, params: *const c_void, + destination_block_state: *mut *mut ZSTD_compressedBlockState_t, + source_block_state: *const ZSTD_compressedBlockState_t, ) -> ZSTD_rust_resetCCtxByCopyingCDictState { ZSTD_rust_resetCCtxByCopyingCDictState { callback_context: (probe as *mut ResetCCtxByCopyingCDictProbe).cast(), @@ -2792,7 +2803,8 @@ mod tests { mark_tables_clean: Some(reset_cctx_by_copying_cdict_mark_clean), copy_match_state: Some(reset_cctx_by_copying_cdict_copy_match_state), copy_dict_state: Some(reset_cctx_by_copying_cdict_copy_dict_state), - copy_block_state: Some(reset_cctx_by_copying_cdict_copy_block_state), + destination_block_state, + source_block_state, zbuff: 7, } } @@ -2802,19 +2814,43 @@ mod tests { let mut probe = ResetCCtxByCopyingCDictProbe::default(); let cdict = 0x4000usize as *const c_void; let params = 0x3000usize as *const c_void; - let state = reset_cctx_by_copying_cdict_test_state(&mut probe, cdict, params); + let mut source_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + source_block_state.rep = [9, 10, 11]; + source_block_state.entropy.huf.repeatMode = HUF_REPEAT_VALID; + source_block_state.entropy.fse.offcode_repeatMode = FSE_REPEAT_VALID; + let mut destination_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + let mut destination_block_state_slot = + &mut destination_block_state as *mut ZSTD_compressedBlockState_t; + let state = reset_cctx_by_copying_cdict_test_state( + &mut probe, + cdict, + params, + &mut destination_block_state_slot, + &source_block_state, + ); let result = unsafe { ZSTD_rust_resetCCtxByCopyingCDict(&state) }; assert_eq!(result, 0); assert_eq!( probe.events, - ["reset", "dirty", "tables", "zero-h3", "clean", "match", "dict", "block"] + ["reset", "dirty", "tables", "zero-h3", "clean", "match", "dict"] ); assert_eq!(probe.cdict, cdict); assert_eq!(probe.params, params); assert_eq!(probe.pledged_src_size, 123); assert_eq!(probe.zbuff, 7); + assert_eq!(destination_block_state.rep, source_block_state.rep); + assert_eq!( + destination_block_state.entropy.huf.repeatMode, + source_block_state.entropy.huf.repeatMode + ); + assert_eq!( + destination_block_state.entropy.fse.offcode_repeatMode, + source_block_state.entropy.fse.offcode_repeatMode + ); } #[test] @@ -2823,10 +2859,18 @@ mod tests { reset_result: ERROR(ZstdErrorCode::MemoryAllocation), ..Default::default() }; + let mut destination_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + let mut destination_block_state_slot = + &mut destination_block_state as *mut ZSTD_compressedBlockState_t; + let source_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; let state = reset_cctx_by_copying_cdict_test_state( &mut probe, 0x4000usize as *const c_void, 0x3000usize as *const c_void, + &mut destination_block_state_slot, + &source_block_state, ); let result = unsafe { ZSTD_rust_resetCCtxByCopyingCDict(&state) }; @@ -2885,19 +2929,12 @@ mod tests { .push("dict"); } - unsafe extern "C" fn reset_cctx_by_attaching_cdict_copy_block_state( - context: *mut c_void, - _cdict: *const c_void, - ) { - unsafe { reset_cctx_by_attaching_cdict_probe(context) } - .events - .push("block"); - } - fn reset_cctx_by_attaching_cdict_test_state( probe: &mut ResetCCtxByAttachingCDictProbe, cdict: *const c_void, params: *const c_void, + destination_block_state: *mut *mut ZSTD_compressedBlockState_t, + source_block_state: *const ZSTD_compressedBlockState_t, ) -> ZSTD_rust_resetCCtxByAttachingCDictState { ZSTD_rust_resetCCtxByAttachingCDictState { callback_context: (probe as *mut ResetCCtxByAttachingCDictProbe).cast(), @@ -2907,7 +2944,8 @@ mod tests { reset: Some(reset_cctx_by_attaching_cdict_reset), attach: Some(reset_cctx_by_attaching_cdict_attach), copy_dict_state: Some(reset_cctx_by_attaching_cdict_copy_dict_state), - copy_block_state: Some(reset_cctx_by_attaching_cdict_copy_block_state), + destination_block_state, + source_block_state, zbuff: 7, } } @@ -2917,16 +2955,35 @@ mod tests { let mut probe = ResetCCtxByAttachingCDictProbe::default(); let cdict = 0x4000usize as *const c_void; let params = 0x3000usize as *const c_void; - let state = reset_cctx_by_attaching_cdict_test_state(&mut probe, cdict, params); + let mut source_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + source_block_state.rep = [12, 13, 14]; + source_block_state.entropy.huf.repeatMode = HUF_REPEAT_VALID; + let mut destination_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + let mut destination_block_state_slot = + &mut destination_block_state as *mut ZSTD_compressedBlockState_t; + let state = reset_cctx_by_attaching_cdict_test_state( + &mut probe, + cdict, + params, + &mut destination_block_state_slot, + &source_block_state, + ); let result = unsafe { ZSTD_rust_resetCCtxByAttachingCDict(&state) }; assert_eq!(result, 0); - assert_eq!(probe.events, ["reset", "attach", "dict", "block"]); + assert_eq!(probe.events, ["reset", "attach", "dict"]); assert_eq!(probe.cdict, cdict); assert_eq!(probe.params, params); assert_eq!(probe.pledged_src_size, 123); assert_eq!(probe.zbuff, 7); + assert_eq!(destination_block_state.rep, source_block_state.rep); + assert_eq!( + destination_block_state.entropy.huf.repeatMode, + source_block_state.entropy.huf.repeatMode + ); } #[test] @@ -2935,10 +2992,18 @@ mod tests { reset_result: ERROR(ZstdErrorCode::MemoryAllocation), ..Default::default() }; + let mut destination_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; + let mut destination_block_state_slot = + &mut destination_block_state as *mut ZSTD_compressedBlockState_t; + let source_block_state = + unsafe { std::mem::MaybeUninit::::zeroed().assume_init() }; let state = reset_cctx_by_attaching_cdict_test_state( &mut probe, 0x4000usize as *const c_void, 0x3000usize as *const c_void, + &mut destination_block_state_slot, + &source_block_state, ); let result = unsafe { ZSTD_rust_resetCCtxByAttachingCDict(&state) };