diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 1613d36af..715295b78 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -954,21 +954,14 @@ typedef char ZSTD_rust_compress_continue_state_layout[ == (sizeof(void*) == 8 ? 120 : 80)) ? 1 : -1]; -/* Rust owns the end-of-frame orchestration. The callbacks retain the - * private CCtx-dependent continue and trace operations in C; checksum and - * frame-epilogue fields are projected explicitly. */ -typedef size_t (*ZSTD_rust_compressEndContinue_f)(void* context, - void* dst, - size_t dstCapacity, - const void* src, - size_t srcSize, - U32 frame, - U32 lastFrameChunk); +/* Rust owns the end-of-frame orchestration. Only the trace operation still + * needs a callback; checksum and frame-epilogue fields are projected + * explicitly, and continue uses the shared direct state projection. */ typedef void (*ZSTD_rust_compressEndTrace_f)(void* context, size_t extraCSize); typedef struct { void* callbackContext; - ZSTD_rust_compressEndContinue_f compressContinue; + const ZSTD_rust_compressContinueState* compressContinueState; ZSTD_rust_compressEndTrace_f trace; unsigned long long* consumedSrcSize; U64 pledgedSrcSizePlusOne; @@ -985,7 +978,7 @@ size_t ZSTD_rust_compressEnd(const ZSTD_rust_compressEndState* state, const void* src, size_t srcSize); typedef char ZSTD_rust_compress_end_state_layout[ (offsetof(ZSTD_rust_compressEndState, callbackContext) == 0 - && offsetof(ZSTD_rust_compressEndState, compressContinue) + && offsetof(ZSTD_rust_compressEndState, compressContinueState) == sizeof(void*) && offsetof(ZSTD_rust_compressEndState, trace) == 2 * sizeof(void*) @@ -5432,6 +5425,20 @@ typedef struct { const ZSTD_CCtx_params* params; } ZSTD_rust_overflowCorrectContext; +/* All continue entry points use this synchronous stack projection. The + * private CCtx and match-state layouts remain behind the direct field + * projections and context-sensitive leaf callbacks. */ +typedef struct { + ZSTD_rust_compressContinueState state; + ZSTD_rust_compressContinueWindowState windowState; + ZSTD_rust_compressContinueWindowState ldmWindowState; + ZSTD_rust_frameChunkState frameChunkState; + ZSTD_rust_frameChunkPrepareState frameChunkPrepareState; + ZSTD_rust_frameChunkClampState frameChunkClampState; + ZSTD_rust_overflowCorrectContext overflowContext; + ZSTD_rust_overflowCorrectState overflowState; +} ZSTD_rust_compressContinueContext; + static int ZSTD_rust_overflowCorrect_need( void* context, const void* src, const void* srcEnd) { @@ -5579,100 +5586,100 @@ static size_t ZSTD_rust_compressContinue_block( 0 /* frame */); } +static void ZSTD_compressContinue_prepare( + ZSTD_CCtx* cctx, size_t blockSizeMax, int checkBlockSize, + ZSTD_rust_compressContinueContext* context) +{ + ZSTD_MatchState_t* const ms = &cctx->blockState.matchState; + ZSTD_window_t* const window = &ms->window; + ZSTD_window_t* const ldmWindow = &cctx->ldmState.window; + + context->windowState.nextSrc = &window->nextSrc; + context->windowState.base = &window->base; + context->windowState.dictBase = &window->dictBase; + context->windowState.dictLimit = &window->dictLimit; + context->windowState.lowLimit = &window->lowLimit; + context->windowState.forceNonContiguous = &ms->forceNonContiguous; + context->windowState.nextToUpdate = &ms->nextToUpdate; + context->ldmWindowState.nextSrc = &ldmWindow->nextSrc; + context->ldmWindowState.base = &ldmWindow->base; + context->ldmWindowState.dictBase = &ldmWindow->dictBase; + context->ldmWindowState.dictLimit = &ldmWindow->dictLimit; + context->ldmWindowState.lowLimit = &ldmWindow->lowLimit; + context->ldmWindowState.forceNonContiguous = NULL; + context->ldmWindowState.nextToUpdate = NULL; + + context->frameChunkPrepareState.callbackContext = cctx; + context->frameChunkPrepareState.maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; + context->frameChunkPrepareState.correctOverflow = ZSTD_rust_frameChunk_correctOverflow; + context->frameChunkPrepareState.checkDictValidity = ZSTD_rust_frameChunk_checkDictValidity; + context->frameChunkPrepareState.enforceMaxDist = ZSTD_rust_frameChunk_enforceMaxDist; + context->frameChunkClampState.nextToUpdate = &ms->nextToUpdate; + context->frameChunkClampState.lowLimit = &ms->window.lowLimit; + context->frameChunkPrepareState.clampState = &context->frameChunkClampState; + context->frameChunkState.callbackContext = cctx; + context->frameChunkState.tmpWorkspace = cctx->tmpWorkspace; + context->frameChunkState.checksumState = &cctx->xxhState; + context->frameChunkState.isFirstBlock = &cctx->isFirstBlock; + context->frameChunkState.stage = &cctx->stage; + context->frameChunkState.tmpWkspSize = cctx->tmpWkspSize; + context->frameChunkState.blockSizeMax = cctx->blockSizeMax; + context->frameChunkState.savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; + context->frameChunkState.preBlockSplitterLevel = cctx->appliedParams.preBlockSplitter_level; + context->frameChunkState.strategy = (int)cctx->appliedParams.cParams.strategy; + context->frameChunkState.useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams); + context->frameChunkState.blockSplitterEnabled = ZSTD_blockSplitterEnabled(&cctx->appliedParams); + context->frameChunkState.checksumFlag = cctx->appliedParams.fParams.checksumFlag; + context->frameChunkState.endingStage = (int)ZSTDcs_ending; + context->frameChunkState.prepareState = &context->frameChunkPrepareState; + context->frameChunkState.compressTarget = ZSTD_rust_frameChunk_compressTarget; + context->frameChunkState.compressSplit = ZSTD_rust_frameChunk_compressSplit; + context->frameChunkState.compressInternal = ZSTD_rust_frameChunk_compressInternal; + + context->overflowContext.matchState = ms; + context->overflowContext.workspace = &cctx->workspace; + context->overflowContext.params = &cctx->appliedParams; + context->overflowState.callbackContext = &context->overflowContext; + context->overflowState.nextToUpdate = &ms->nextToUpdate; + context->overflowState.needCorrection = ZSTD_rust_overflowCorrect_need; + context->overflowState.correctOverflow = ZSTD_rust_overflowCorrect_correct; + context->overflowState.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty; + context->overflowState.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex; + context->overflowState.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean; + context->overflowState.loadedDictEnd = &ms->loadedDictEnd; + context->overflowState.dictMatchState = &ms->dictMatchState; + + context->state.callbackContext = cctx; + context->state.windowState = &context->windowState; + context->state.ldmWindowState = &context->ldmWindowState; + context->state.overflowState = &context->overflowState; + context->state.frameChunkState = &context->frameChunkState; + context->state.compressBlock = ZSTD_rust_compressContinue_block; + context->state.stage = &cctx->stage; + context->state.consumedSrcSize = &cctx->consumedSrcSize; + context->state.producedCSize = &cctx->producedCSize; + context->state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne; + context->state.blockSizeMax = blockSizeMax; + context->state.checkBlockSize = checkBlockSize; + context->state.noDictIDFlag = cctx->appliedParams.fParams.noDictIDFlag; + context->state.checksumFlag = cctx->appliedParams.fParams.checksumFlag; + context->state.contentSizeFlag = cctx->appliedParams.fParams.contentSizeFlag; + context->state.format = (int)cctx->appliedParams.format; + context->state.windowLog = cctx->appliedParams.cParams.windowLog; + context->state.dictID = cctx->dictID; + context->state.ldmEnabled = cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable; +} + static size_t ZSTD_compressContinue_dispatch( ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 frame, U32 lastFrameChunk, size_t blockSizeMax, int checkBlockSize) { - ZSTD_rust_compressContinueState state; - ZSTD_rust_compressContinueWindowState windowState; - ZSTD_rust_compressContinueWindowState ldmWindowState; - ZSTD_rust_frameChunkState frameChunkState; - ZSTD_rust_frameChunkPrepareState frameChunkPrepareState; - ZSTD_rust_frameChunkClampState frameChunkClampState; - ZSTD_rust_overflowCorrectContext overflowContext; - ZSTD_rust_overflowCorrectState overflowState; - ZSTD_MatchState_t* const ms = &cctx->blockState.matchState; - ZSTD_window_t* const window = &ms->window; - ZSTD_window_t* const ldmWindow = &cctx->ldmState.window; - - windowState.nextSrc = &window->nextSrc; - windowState.base = &window->base; - windowState.dictBase = &window->dictBase; - windowState.dictLimit = &window->dictLimit; - windowState.lowLimit = &window->lowLimit; - windowState.forceNonContiguous = &ms->forceNonContiguous; - windowState.nextToUpdate = &ms->nextToUpdate; - ldmWindowState.nextSrc = &ldmWindow->nextSrc; - ldmWindowState.base = &ldmWindow->base; - ldmWindowState.dictBase = &ldmWindow->dictBase; - ldmWindowState.dictLimit = &ldmWindow->dictLimit; - ldmWindowState.lowLimit = &ldmWindow->lowLimit; - ldmWindowState.forceNonContiguous = NULL; - ldmWindowState.nextToUpdate = NULL; - - frameChunkPrepareState.callbackContext = cctx; - frameChunkPrepareState.maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; - frameChunkPrepareState.correctOverflow = ZSTD_rust_frameChunk_correctOverflow; - frameChunkPrepareState.checkDictValidity = ZSTD_rust_frameChunk_checkDictValidity; - frameChunkPrepareState.enforceMaxDist = ZSTD_rust_frameChunk_enforceMaxDist; - frameChunkClampState.nextToUpdate = &ms->nextToUpdate; - frameChunkClampState.lowLimit = &ms->window.lowLimit; - frameChunkPrepareState.clampState = &frameChunkClampState; - frameChunkState.callbackContext = cctx; - frameChunkState.tmpWorkspace = cctx->tmpWorkspace; - frameChunkState.checksumState = &cctx->xxhState; - frameChunkState.isFirstBlock = &cctx->isFirstBlock; - frameChunkState.stage = &cctx->stage; - frameChunkState.tmpWkspSize = cctx->tmpWkspSize; - frameChunkState.blockSizeMax = cctx->blockSizeMax; - frameChunkState.savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize; - frameChunkState.preBlockSplitterLevel = cctx->appliedParams.preBlockSplitter_level; - frameChunkState.strategy = (int)cctx->appliedParams.cParams.strategy; - frameChunkState.useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams); - frameChunkState.blockSplitterEnabled = ZSTD_blockSplitterEnabled(&cctx->appliedParams); - frameChunkState.checksumFlag = cctx->appliedParams.fParams.checksumFlag; - frameChunkState.endingStage = (int)ZSTDcs_ending; - frameChunkState.prepareState = &frameChunkPrepareState; - frameChunkState.compressTarget = ZSTD_rust_frameChunk_compressTarget; - frameChunkState.compressSplit = ZSTD_rust_frameChunk_compressSplit; - frameChunkState.compressInternal = ZSTD_rust_frameChunk_compressInternal; - - overflowContext.matchState = ms; - overflowContext.workspace = &cctx->workspace; - overflowContext.params = &cctx->appliedParams; - overflowState.callbackContext = &overflowContext; - overflowState.nextToUpdate = &ms->nextToUpdate; - overflowState.needCorrection = ZSTD_rust_overflowCorrect_need; - overflowState.correctOverflow = ZSTD_rust_overflowCorrect_correct; - overflowState.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty; - overflowState.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex; - overflowState.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean; - overflowState.loadedDictEnd = &ms->loadedDictEnd; - overflowState.dictMatchState = &ms->dictMatchState; - - state.callbackContext = cctx; - state.windowState = &windowState; - state.ldmWindowState = &ldmWindowState; - state.overflowState = &overflowState; - state.frameChunkState = &frameChunkState; - state.compressBlock = ZSTD_rust_compressContinue_block; - state.stage = &cctx->stage; - state.consumedSrcSize = &cctx->consumedSrcSize; - state.producedCSize = &cctx->producedCSize; - state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne; - state.blockSizeMax = blockSizeMax; - state.checkBlockSize = checkBlockSize; - state.noDictIDFlag = cctx->appliedParams.fParams.noDictIDFlag; - state.checksumFlag = cctx->appliedParams.fParams.checksumFlag; - state.contentSizeFlag = cctx->appliedParams.fParams.contentSizeFlag; - state.format = (int)cctx->appliedParams.format; - state.windowLog = cctx->appliedParams.cParams.windowLog; - state.dictID = cctx->dictID; - state.ldmEnabled = cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable; + ZSTD_rust_compressContinueContext context; + ZSTD_compressContinue_prepare(cctx, blockSizeMax, checkBlockSize, &context); return ZSTD_rust_compressContinue( - &state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk); + &context.state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk); } void ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq) @@ -6178,17 +6185,6 @@ void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize) #endif } -static size_t ZSTD_rust_compressEnd_continue( - void* context, void* dst, size_t dstCapacity, - const void* src, size_t srcSize, U32 frame, U32 lastFrameChunk) -{ - ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; - return ZSTD_compressContinue_dispatch( - cctx, dst, dstCapacity, src, srcSize, - frame, lastFrameChunk, cctx->blockSizeMax, - 0 /* block size already selected */); -} - static void ZSTD_rust_compressEnd_trace(void* context, size_t extraCSize) { ZSTD_CCtx_trace((ZSTD_CCtx*)context, extraCSize); @@ -6198,9 +6194,12 @@ size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) { + ZSTD_rust_compressContinueContext continueContext; ZSTD_rust_compressEndState state; + ZSTD_compressContinue_prepare(cctx, cctx->blockSizeMax, + 0 /* block size already selected */, &continueContext); state.callbackContext = cctx; - state.compressContinue = ZSTD_rust_compressEnd_continue; + state.compressContinueState = &continueContext.state; state.trace = ZSTD_rust_compressEnd_trace; state.consumedSrcSize = &cctx->consumedSrcSize; state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne; diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index b6e4c925f..2a6ca5b0c 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -1146,27 +1146,18 @@ pub unsafe extern "C" fn ZSTD_rust_compressContinue( } } -type CompressEndContinueFn = unsafe extern "C" fn( - *mut c_void, - *mut c_void, - usize, - *const c_void, - usize, - c_uint, - c_uint, -) -> usize; type CompressEndTraceFn = unsafe extern "C" fn(*mut c_void, usize); /// Explicit projection for the public end-of-frame orchestration. /// /// Rust owns callback ordering, output offset/capacity accounting, and -/// pledged-size validation. The opaque callback context retains only the -/// private CCtx-dependent continue and trace operations in C; Rust serializes -/// the epilogue from explicit frame and checksum projections. +/// pledged-size validation. The continue state is projected explicitly and +/// the opaque callback context retains only the private trace operation in C; +/// Rust serializes the epilogue from explicit frame and checksum projections. #[repr(C)] pub struct ZSTD_rust_compressEndState { callback_context: *mut c_void, - compress_continue: CompressEndContinueFn, + compress_continue_state: *const ZSTD_rust_compressContinueState, trace: CompressEndTraceFn, consumed_src_size: *const u64, pledged_src_size_plus_one: u64, @@ -1181,7 +1172,7 @@ pub struct ZSTD_rust_compressEndState { const _: () = { assert!(offset_of!(ZSTD_rust_compressEndState, callback_context) == 0); - assert!(offset_of!(ZSTD_rust_compressEndState, compress_continue) == size_of::()); + assert!(offset_of!(ZSTD_rust_compressEndState, compress_continue_state) == size_of::()); assert!(offset_of!(ZSTD_rust_compressEndState, trace) == 2 * size_of::()); assert!(offset_of!(ZSTD_rust_compressEndState, consumed_src_size) == 3 * size_of::()); assert!( @@ -1229,14 +1220,17 @@ unsafe fn compress_end_body_with( src: *const c_void, src_size: usize, ) -> usize { - if state.consumed_src_size.is_null() || state.stage.is_null() || state.checksum_state.is_null() + if state.compress_continue_state.is_null() + || state.consumed_src_size.is_null() + || state.stage.is_null() + || state.checksum_state.is_null() { return ERROR(ZstdErrorCode::Generic); } let c_size = unsafe { - (state.compress_continue)( - state.callback_context, + ZSTD_rust_compressContinue( + state.compress_continue_state, dst, dst_capacity, src, @@ -10155,6 +10149,16 @@ mod tests { continue_frame: c_uint, continue_last_frame_chunk: c_uint, stage: c_int, + window: ZSTD_rust_windowUpdateState, + force_non_contiguous: c_int, + next_to_update: c_uint, + window_projection: ZSTD_rust_compressContinueWindowProjection, + frame_chunk_clamp_state: Option, + frame_chunk_prepare_state: Option, + frame_chunk_state: Option, + continue_state: Option, + is_first_block: c_int, + produced_c_size: u64, } static COMPRESS_END_TEST_CHECKSUM_STATE: XXH64_state_t = XXH64_state_t { @@ -10172,19 +10176,33 @@ mod tests { unsafe { &mut *context.cast::() } } - unsafe extern "C" fn compress_end_test_continue( + unsafe extern "C" fn compress_end_test_frame_prepare_overflow( + _context: *mut c_void, + _src: *const c_void, + _block_size: usize, + ) { + } + + unsafe extern "C" fn compress_end_test_frame_prepare_window( + _context: *mut c_void, + _src: *const c_void, + _block_size: usize, + _max_dist: c_uint, + ) { + } + + unsafe extern "C" fn compress_end_test_frame_target( context: *mut c_void, _dst: *mut c_void, _dst_capacity: usize, _src: *const c_void, _src_size: usize, - frame: c_uint, - last_frame_chunk: c_uint, + last_block: c_uint, ) -> usize { let context = unsafe { compress_end_test_context(context) }; context.events.push("continue"); - context.continue_frame = frame; - context.continue_last_frame_chunk = last_frame_chunk; + context.continue_frame = 1; + context.continue_last_frame_chunk = last_block; context.continue_result } @@ -10196,14 +10214,105 @@ mod tests { fn compress_end_test_state( context: &mut CompressEndTestContext, - consumed_src_size: &u64, + consumed_src_size: &mut u64, pledged_src_size_plus_one: u64, content_size_flag: c_int, ) -> ZSTD_rust_compressEndState { - context.stage = 1; + let base = WINDOW_INIT_SENTINEL.as_ptr().cast::(); + context.stage = ZSTD_COMPRESSION_STAGE_ONGOING; + context.window = ZSTD_rust_windowUpdateState { + nextSrc: base, + base, + dictBase: base, + dictLimit: ZSTD_WINDOW_START_INDEX, + lowLimit: ZSTD_WINDOW_START_INDEX, + }; + context.force_non_contiguous = 0; + context.next_to_update = ZSTD_WINDOW_START_INDEX; + context.is_first_block = 1; + context.produced_c_size = 0; + context.window_projection = ZSTD_rust_compressContinueWindowProjection { + next_src: ptr::addr_of_mut!(context.window.nextSrc), + base: ptr::addr_of_mut!(context.window.base), + dict_base: ptr::addr_of_mut!(context.window.dictBase), + dict_limit: ptr::addr_of_mut!(context.window.dictLimit), + low_limit: ptr::addr_of_mut!(context.window.lowLimit), + force_non_contiguous: ptr::addr_of_mut!(context.force_non_contiguous), + next_to_update: ptr::addr_of_mut!(context.next_to_update), + }; + let callback_context = (context as *mut CompressEndTestContext).cast(); + context.frame_chunk_clamp_state = Some(ZSTD_rust_frameChunkClampState { + next_to_update: ptr::addr_of_mut!(context.next_to_update), + low_limit: ptr::addr_of!(context.window.lowLimit), + }); + let frame_chunk_clamp_state = context + .frame_chunk_clamp_state + .as_ref() + .map_or(ptr::null(), |state| state as *const _); + context.frame_chunk_prepare_state = Some(ZSTD_rust_frameChunkPrepareState { + callback_context, + max_dist: 64, + correct_overflow: compress_end_test_frame_prepare_overflow, + check_dict_validity: compress_end_test_frame_prepare_window, + enforce_max_dist: compress_end_test_frame_prepare_window, + clamp_state: frame_chunk_clamp_state, + }); + let frame_chunk_prepare_state = context + .frame_chunk_prepare_state + .as_ref() + .map_or(ptr::null(), |state| state as *const _); + context.frame_chunk_state = Some(ZSTD_rust_frameChunkState { + callback_context, + tmp_workspace: ptr::null_mut(), + checksum_state: ptr::null_mut(), + is_first_block: ptr::addr_of_mut!(context.is_first_block), + stage: ptr::addr_of_mut!(context.stage), + tmp_wksp_size: 0, + block_size_max: 1, + savings: 0, + pre_block_splitter_level: 1, + strategy: ZSTD_FAST, + use_target_c_block_size: 1, + block_splitter_enabled: 0, + checksum_flag: 0, + ending_stage: ZSTD_COMPRESSION_STAGE_ENDING, + prepare_state: frame_chunk_prepare_state, + compress_target: compress_end_test_frame_target, + compress_split: compress_end_test_frame_target, + compress_internal: compress_end_test_frame_target, + }); + let frame_chunk_state = context + .frame_chunk_state + .as_ref() + .map_or(ptr::null(), |state| state as *const _); + context.continue_state = Some(ZSTD_rust_compressContinueState { + callback_context, + window_state: &context.window_projection, + ldm_window_state: ptr::null(), + overflow_state: ptr::null(), + frame_chunk_state, + compress_block: compress_end_test_frame_target, + stage: ptr::addr_of_mut!(context.stage), + consumed_src_size: consumed_src_size as *mut u64, + produced_c_size: ptr::addr_of_mut!(context.produced_c_size), + pledged_src_size_plus_one, + block_size_max: 1, + check_block_size: 0, + no_dict_id_flag: 0, + checksum_flag: 0, + content_size_flag: 0, + format: 0, + window_log: 20, + dict_id: 0, + ldm_enabled: 0, + }); + let continue_state = context + .continue_state + .as_ref() + .map_or(ptr::null(), |state| state as *const _); ZSTD_rust_compressEndState { - callback_context: (context as *mut CompressEndTestContext).cast(), - compress_continue: compress_end_test_continue, + callback_context, + compress_continue_state: continue_state, trace: compress_end_test_trace, consumed_src_size: consumed_src_size as *const u64, pledged_src_size_plus_one, @@ -10224,20 +10333,28 @@ mod tests { continue_result: 3, ..CompressEndTestContext::default() }; - let consumed_src_size = 7; - let state = compress_end_test_state(&mut context, &consumed_src_size, 8, 1); + let mut consumed_src_size = 7; + let state = compress_end_test_state(&mut context, &mut consumed_src_size, 9, 1); + let source = [0u8; 1]; let result = unsafe { - ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0) + ZSTD_rust_compressEnd( + &state, + dst.as_mut_ptr().cast(), + dst.len(), + source.as_ptr().cast(), + source.len(), + ) }; - assert_eq!(result, 16); + assert_eq!(result, 7); assert_eq!(context.events, ["continue", "trace"]); assert_eq!( (context.continue_frame, context.continue_last_frame_chunk), (1, 1) ); - assert_eq!(context.trace_extra, 13); + assert_eq!(context.trace_extra, 4); + assert_eq!((consumed_src_size, context.produced_c_size), (8, 3)); assert_eq!(context.stage, 0); } @@ -10248,11 +10365,18 @@ mod tests { continue_result: ERROR(ZstdErrorCode::MemoryAllocation), ..CompressEndTestContext::default() }; - let consumed_src_size = 7; - let state = compress_end_test_state(&mut context, &consumed_src_size, 8, 0); + let mut consumed_src_size = 7; + let state = compress_end_test_state(&mut context, &mut consumed_src_size, 8, 0); + let source = [0u8; 1]; let result = unsafe { - ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0) + ZSTD_rust_compressEnd( + &state, + dst.as_mut_ptr().cast(), + dst.len(), + source.as_ptr().cast(), + source.len(), + ) }; assert_eq!(result, ERROR(ZstdErrorCode::MemoryAllocation)); @@ -10261,16 +10385,23 @@ mod tests { #[test] fn compress_end_stops_before_validation_and_trace_when_epilogue_fails() { - let mut dst = [0u8; 8]; + let mut dst = [0u8; 6]; let mut context = CompressEndTestContext { continue_result: 3, ..CompressEndTestContext::default() }; - let consumed_src_size = 7; - let state = compress_end_test_state(&mut context, &consumed_src_size, 99, 1); + let mut consumed_src_size = 7; + let state = compress_end_test_state(&mut context, &mut consumed_src_size, 99, 1); + let source = [0u8; 1]; let result = unsafe { - ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0) + ZSTD_rust_compressEnd( + &state, + dst.as_mut_ptr().cast(), + dst.len(), + source.as_ptr().cast(), + source.len(), + ) }; assert_eq!(result, ERROR(ZstdErrorCode::DstSizeTooSmall)); @@ -10284,11 +10415,18 @@ mod tests { continue_result: 3, ..CompressEndTestContext::default() }; - let consumed_src_size = 7; - let state = compress_end_test_state(&mut context, &consumed_src_size, 99, 1); + let mut consumed_src_size = 7; + let state = compress_end_test_state(&mut context, &mut consumed_src_size, 99, 1); + let source = [0u8; 1]; let result = unsafe { - ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0) + ZSTD_rust_compressEnd( + &state, + dst.as_mut_ptr().cast(), + dst.len(), + source.as_ptr().cast(), + source.len(), + ) }; assert_eq!(result, ERROR(ZstdErrorCode::SrcSizeWrong));