diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 69a2d36f8..90a3fa1d5 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2280,21 +2280,67 @@ typedef char ZSTD_rust_reset_cctx_workspace_state_layout[ ? 1 : -1]; typedef struct { void* callbackContext; - ZSTD_rust_resetCCtxStorageCallback_f initialize; + ZSTD_rust_resetCCtxStorageCallback_f resetHash; void* compressedBlockState; ZSTD_rust_resetCCtxTailCallback_f resetMatchState; ZSTD_rust_resetCCtxTailCallback_f resetStorage; + ZSTD_compressionParameters* matchStateCParams; + int* matchStatePrefetchCDictTables; + unsigned long long* pledgedSrcSizePlusOne; + unsigned long long* consumedSrcSize; + unsigned long long* producedCSize; + int* contentSizeFlag; + size_t* blockSizeMax; + int* stage; + U32* dictID; + size_t* dictContentSize; + ZSTD_compressionParameters cParams; + int prefetchCDictTables; + U64 pledgedSrcSize; + size_t blockSize; } ZSTD_rust_resetCCtxTailState; typedef char ZSTD_rust_reset_cctx_tail_state_layout[ (offsetof(ZSTD_rust_resetCCtxTailState, callbackContext) == 0 - && offsetof(ZSTD_rust_resetCCtxTailState, initialize) == sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, resetHash) == sizeof(void*) && offsetof(ZSTD_rust_resetCCtxTailState, compressedBlockState) == 2 * sizeof(void*) && offsetof(ZSTD_rust_resetCCtxTailState, resetMatchState) == 3 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, resetStorage) + == 4 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, matchStateCParams) + == 5 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, matchStatePrefetchCDictTables) + == 6 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, pledgedSrcSizePlusOne) + == 7 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, consumedSrcSize) + == 8 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, producedCSize) + == 9 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, contentSizeFlag) + == 10 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, blockSizeMax) + == 11 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, stage) + == 12 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, dictID) + == 13 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, dictContentSize) + == 14 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, cParams) + == 15 * sizeof(void*) + && offsetof(ZSTD_rust_resetCCtxTailState, prefetchCDictTables) + == offsetof(ZSTD_rust_resetCCtxTailState, cParams) + + sizeof(ZSTD_compressionParameters) + && offsetof(ZSTD_rust_resetCCtxTailState, pledgedSrcSize) + > offsetof(ZSTD_rust_resetCCtxTailState, prefetchCDictTables) + && offsetof(ZSTD_rust_resetCCtxTailState, blockSize) + == offsetof(ZSTD_rust_resetCCtxTailState, pledgedSrcSize) + + sizeof(U64) && sizeof(ZSTD_rust_resetCCtxTailState) - == offsetof(ZSTD_rust_resetCCtxTailState, resetStorage) - + sizeof(void*)) + == offsetof(ZSTD_rust_resetCCtxTailState, blockSize) + + sizeof(size_t)) ? 1 : -1]; typedef struct { void* callbackContext; @@ -5238,8 +5284,6 @@ static void ZSTD_rust_resetCCtxWorkspace_clear(void* opaque) typedef struct { ZSTD_CCtx* cctx; const ZSTD_CCtx_params* params; - size_t blockSize; - U64 pledgedSrcSize; ZSTD_cwksp* ws; ZSTD_compResetPolicy_e compResetPolicy; ZSTD_indexResetPolicy_e indexResetPolicy; @@ -5270,34 +5314,21 @@ static void ZSTD_rust_resetCCtxTail_prepare( { ZSTD_rust_resetCCtxTailContext* const context = (ZSTD_rust_resetCCtxTailContext*)opaque; - context->blockSize = blockSize; context->indexResetPolicy = (ZSTD_indexResetPolicy_e)indexResetPolicy; + context->tailState->blockSize = blockSize; context->tailState->compressedBlockState = context->cctx->blockState.prevCBlock; } -static void ZSTD_rust_resetCCtxTail_initialize(void* opaque) +static void ZSTD_rust_resetCCtxTail_resetHash(void* opaque) { ZSTD_rust_resetCCtxTailContext* const context = (ZSTD_rust_resetCCtxTailContext*)opaque; ZSTD_CCtx* const cctx = context->cctx; - cctx->blockState.matchState.cParams = context->params->cParams; - cctx->blockState.matchState.prefetchCDictTables = - context->params->prefetchCDictTables == ZSTD_ps_enable; - cctx->pledgedSrcSizePlusOne = context->pledgedSrcSize + 1; - cctx->consumedSrcSize = 0; - cctx->producedCSize = 0; - if (context->pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN) - cctx->appliedParams.fParams.contentSizeFlag = 0; DEBUGLOG(4, "pledged content size : %u ; flag : %u", - (unsigned)context->pledgedSrcSize, + (unsigned)cctx->pledgedSrcSizePlusOne - 1, cctx->appliedParams.fParams.contentSizeFlag); - cctx->blockSizeMax = context->blockSize; - XXH64_reset(&cctx->xxhState, 0); - cctx->stage = ZSTDcs_init; - cctx->dictID = 0; - cctx->dictContentSize = 0; } static size_t ZSTD_rust_resetCCtxTail_resetMatchState(void* opaque) @@ -5450,18 +5481,31 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, tailContext.cctx = zc; tailContext.params = params; - tailContext.blockSize = 0; - tailContext.pledgedSrcSize = pledgedSrcSize; tailContext.ws = ws; tailContext.compResetPolicy = crp; tailContext.indexResetPolicy = needsIndexReset; tailContext.storageState = &storageState; tailContext.tailState = &tailState; tailState.callbackContext = &tailContext; - tailState.initialize = ZSTD_rust_resetCCtxTail_initialize; + tailState.resetHash = ZSTD_rust_resetCCtxTail_resetHash; tailState.compressedBlockState = NULL; tailState.resetMatchState = ZSTD_rust_resetCCtxTail_resetMatchState; tailState.resetStorage = ZSTD_rust_resetCCtxTail_resetStorage; + tailState.matchStateCParams = &zc->blockState.matchState.cParams; + tailState.matchStatePrefetchCDictTables = + &zc->blockState.matchState.prefetchCDictTables; + tailState.pledgedSrcSizePlusOne = &zc->pledgedSrcSizePlusOne; + tailState.consumedSrcSize = &zc->consumedSrcSize; + tailState.producedCSize = &zc->producedCSize; + tailState.contentSizeFlag = &zc->appliedParams.fParams.contentSizeFlag; + tailState.blockSizeMax = &zc->blockSizeMax; + tailState.stage = (int*)&zc->stage; + tailState.dictID = &zc->dictID; + tailState.dictContentSize = &zc->dictContentSize; + tailState.cParams = params->cParams; + tailState.prefetchCDictTables = (int)params->prefetchCDictTables; + tailState.pledgedSrcSize = pledgedSrcSize; + tailState.blockSize = 0; internalState.callbackContext = &tailContext; internalState.resetState = &resetState; diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index a3f20c724..4459c3a5e 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -9401,22 +9401,81 @@ const _: () = { #[repr(C)] pub struct ZSTD_rust_resetCCtxTailState { callbackContext: *mut c_void, - initialize: Option, + resetHash: Option, compressedBlockState: *mut ZSTD_compressedBlockState_t, resetMatchState: Option, resetStorage: Option, + matchStateCParams: *mut ZSTD_compressionParameters, + matchStatePrefetchCDictTables: *mut c_int, + pledgedSrcSizePlusOne: *mut u64, + consumedSrcSize: *mut u64, + producedCSize: *mut u64, + contentSizeFlag: *mut c_int, + blockSizeMax: *mut usize, + stage: *mut c_int, + dictID: *mut c_uint, + dictContentSize: *mut usize, + cParams: ZSTD_compressionParameters, + prefetchCDictTables: c_int, + pledgedSrcSize: u64, + blockSize: usize, } const _: () = { assert!(offset_of!(ZSTD_rust_resetCCtxTailState, callbackContext) == 0); - assert!(offset_of!(ZSTD_rust_resetCCtxTailState, initialize) == size_of::()); + assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetHash) == size_of::()); assert!( offset_of!(ZSTD_rust_resetCCtxTailState, compressedBlockState) == 2 * size_of::() ); assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetMatchState) == 3 * size_of::()); + assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetStorage) == 4 * size_of::()); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, matchStateCParams) == 5 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, matchStatePrefetchCDictTables) + == 6 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, pledgedSrcSizePlusOne) + == 7 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, consumedSrcSize) == 8 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, producedCSize) == 9 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, contentSizeFlag) == 10 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, blockSizeMax) == 11 * size_of::() + ); + assert!(offset_of!(ZSTD_rust_resetCCtxTailState, stage) == 12 * size_of::()); + assert!(offset_of!(ZSTD_rust_resetCCtxTailState, dictID) == 13 * size_of::()); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, dictContentSize) == 14 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, cParams) == 15 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, prefetchCDictTables) + == offset_of!(ZSTD_rust_resetCCtxTailState, cParams) + + size_of::() + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, pledgedSrcSize) + > offset_of!(ZSTD_rust_resetCCtxTailState, prefetchCDictTables) + ); + assert!( + offset_of!(ZSTD_rust_resetCCtxTailState, blockSize) + == offset_of!(ZSTD_rust_resetCCtxTailState, pledgedSrcSize) + size_of::() + ); assert!( size_of::() - == offset_of!(ZSTD_rust_resetCCtxTailState, resetStorage) + size_of::() + == offset_of!(ZSTD_rust_resetCCtxTailState, blockSize) + size_of::() ); }; @@ -9863,7 +9922,7 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxTail( if state.callbackContext.is_null() { return ERROR(ZstdErrorCode::Generic); } - let Some(initialize) = state.initialize else { + let Some(reset_hash) = state.resetHash else { return ERROR(ZstdErrorCode::Generic); }; let Some(reset_match_state) = state.resetMatchState else { @@ -9875,9 +9934,35 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxTail( if state.compressedBlockState.is_null() { return ERROR(ZstdErrorCode::Generic); } + if state.matchStateCParams.is_null() + || state.matchStatePrefetchCDictTables.is_null() + || state.pledgedSrcSizePlusOne.is_null() + || state.consumedSrcSize.is_null() + || state.producedCSize.is_null() + || state.contentSizeFlag.is_null() + || state.blockSizeMax.is_null() + || state.stage.is_null() + || state.dictID.is_null() + || state.dictContentSize.is_null() + { + return ERROR(ZstdErrorCode::Generic); + } unsafe { - initialize(state.callbackContext); + *state.matchStateCParams = state.cParams; + *state.matchStatePrefetchCDictTables = + c_int::from(state.prefetchCDictTables == ZSTD_RUST_PS_ENABLE); + *state.pledgedSrcSizePlusOne = state.pledgedSrcSize.wrapping_add(1); + *state.consumedSrcSize = 0; + *state.producedCSize = 0; + if state.pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN { + *state.contentSizeFlag = 0; + } + *state.blockSizeMax = state.blockSize; + reset_hash(state.callbackContext); + *state.stage = ZSTD_COMPRESSION_STAGE_INIT; + *state.dictID = 0; + *state.dictContentSize = 0; ZSTD_rust_resetCompressedBlockState(state.compressedBlockState); let result = reset_match_state(state.callbackContext); if ERR_isError(result) { @@ -22547,6 +22632,20 @@ mod tests { events: Vec<&'static str>, match_result: usize, storage_result: usize, + c_params: ZSTD_compressionParameters, + prefetch_cdict_tables: c_int, + pledged_src_size: u64, + block_size: usize, + match_state_cparams: ZSTD_compressionParameters, + match_state_prefetch_cdict_tables: c_int, + pledged_src_size_plus_one: u64, + consumed_src_size: u64, + produced_c_size: u64, + content_size_flag: c_int, + block_size_max: usize, + stage: c_int, + dict_id: c_uint, + dict_content_size: usize, } unsafe fn reset_cctx_tail_test_context( @@ -22555,9 +22654,9 @@ mod tests { unsafe { &mut *context.cast::() } } - unsafe extern "C" fn reset_cctx_tail_test_initialize(context: *mut c_void) { + unsafe extern "C" fn reset_cctx_tail_test_reset_hash(context: *mut c_void) { let context = unsafe { reset_cctx_tail_test_context(context) }; - context.events.push("initialize"); + context.events.push("reset-hash"); } unsafe extern "C" fn reset_cctx_tail_test_reset_match_state(context: *mut c_void) -> usize { @@ -22578,10 +22677,26 @@ mod tests { ) -> ZSTD_rust_resetCCtxTailState { ZSTD_rust_resetCCtxTailState { callbackContext: (context as *mut ResetCCtxTailTestContext).cast(), - initialize: Some(reset_cctx_tail_test_initialize), + resetHash: Some(reset_cctx_tail_test_reset_hash), compressedBlockState: compressed_block_state, resetMatchState: Some(reset_cctx_tail_test_reset_match_state), resetStorage: Some(reset_cctx_tail_test_reset_storage), + matchStateCParams: ptr::addr_of_mut!(context.match_state_cparams), + matchStatePrefetchCDictTables: ptr::addr_of_mut!( + context.match_state_prefetch_cdict_tables + ), + pledgedSrcSizePlusOne: ptr::addr_of_mut!(context.pledged_src_size_plus_one), + consumedSrcSize: ptr::addr_of_mut!(context.consumed_src_size), + producedCSize: ptr::addr_of_mut!(context.produced_c_size), + contentSizeFlag: ptr::addr_of_mut!(context.content_size_flag), + blockSizeMax: ptr::addr_of_mut!(context.block_size_max), + stage: ptr::addr_of_mut!(context.stage), + dictID: ptr::addr_of_mut!(context.dict_id), + dictContentSize: ptr::addr_of_mut!(context.dict_content_size), + cParams: context.c_params, + prefetchCDictTables: context.prefetch_cdict_tables, + pledgedSrcSize: context.pledged_src_size, + blockSize: context.block_size, } } @@ -22595,12 +22710,56 @@ mod tests { assert_eq!(unsafe { ZSTD_rust_resetCCtxTail(&state) }, 0); assert_eq!( context.events, - ["initialize", "reset-match-state", "reset-storage"] + ["reset-hash", "reset-match-state", "reset-storage"] ); assert_eq!(block_state.rep, [1, 4, 8]); assert_eq!(block_state.entropy.huf.repeatMode, 0); } + #[test] + fn cctx_reset_tail_initializes_projected_scalars() { + let c_params = ZSTD_compressionParameters { + windowLog: 20, + chainLog: 18, + hashLog: 19, + searchLog: 3, + minMatch: 4, + targetLength: 8, + strategy: ZSTD_BTLAZY2, + }; + let mut context = ResetCCtxTailTestContext { + c_params, + prefetch_cdict_tables: ZSTD_RUST_PS_ENABLE, + pledged_src_size: ZSTD_CONTENTSIZE_UNKNOWN, + block_size: 4096, + match_state_prefetch_cdict_tables: -1, + pledged_src_size_plus_one: 11, + consumed_src_size: 22, + produced_c_size: 33, + content_size_flag: 1, + block_size_max: 44, + stage: ZSTD_COMPRESSION_STAGE_ONGOING, + dict_id: 55, + dict_content_size: 66, + ..ResetCCtxTailTestContext::default() + }; + let mut block_state = + unsafe { MaybeUninit::::zeroed().assume_init() }; + let state = reset_cctx_tail_test_state(&mut context, &mut block_state); + + assert_eq!(unsafe { ZSTD_rust_resetCCtxTail(&state) }, 0); + assert_eq!(context.match_state_cparams, c_params); + assert_eq!(context.match_state_prefetch_cdict_tables, 1); + assert_eq!(context.pledged_src_size_plus_one, 0); + assert_eq!(context.consumed_src_size, 0); + assert_eq!(context.produced_c_size, 0); + assert_eq!(context.content_size_flag, 0); + assert_eq!(context.block_size_max, 4096); + assert_eq!(context.stage, ZSTD_COMPRESSION_STAGE_INIT); + assert_eq!(context.dict_id, 0); + assert_eq!(context.dict_content_size, 0); + } + #[test] fn cctx_reset_tail_stops_before_storage_after_match_state_error() { let mut context = ResetCCtxTailTestContext { @@ -22615,7 +22774,7 @@ mod tests { unsafe { ZSTD_rust_resetCCtxTail(&state) }, ERROR(ZstdErrorCode::StageWrong) ); - assert_eq!(context.events, ["initialize", "reset-match-state"]); + assert_eq!(context.events, ["reset-hash", "reset-match-state"]); } #[test] @@ -22634,7 +22793,7 @@ mod tests { ); assert_eq!( context.events, - ["initialize", "reset-match-state", "reset-storage"] + ["reset-hash", "reset-match-state", "reset-storage"] ); }