diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3b63f1cdb..2724ba111 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -878,8 +878,20 @@ typedef char ZSTD_rust_frame_chunk_state_layout[ ? 1 : -1]; /* The high-level continue/block entry points are Rust-owned. This projection - * carries frame-header scalars, mutable state, and C callbacks; the private - * CCtx and match-state layout never crosses the ABI. */ + * carries frame-header scalars, mutable state, and C callbacks. Window + * advancement uses direct pointers to the C-owned fields; the private CCtx + * and match-state layout never crosses the ABI. */ +typedef struct { + void* nextSrc; + void* base; + void* dictBase; + void* dictLimit; + void* lowLimit; + void* forceNonContiguous; + void* nextToUpdate; +} ZSTD_rust_compressContinueWindowState; +typedef char ZSTD_rust_compress_continue_window_state_layout[ + (sizeof(ZSTD_rust_compressContinueWindowState) == 7 * sizeof(void*)) ? 1 : -1]; typedef void (*ZSTD_rust_compressContinueWindow_f)(void* context, const void* src, size_t srcSize); @@ -891,7 +903,8 @@ typedef size_t (*ZSTD_rust_compressContinueBlock_f)(void* context, U32 lastFrameChunk); typedef struct { void* callbackContext; - ZSTD_rust_compressContinueWindow_f updateWindow; + ZSTD_rust_compressContinueWindowState* windowState; + ZSTD_rust_compressContinueWindowState* ldmWindowState; ZSTD_rust_compressContinueWindow_f correctOverflow; ZSTD_rust_compressContinueBlock_f compressFrameChunk; ZSTD_rust_compressContinueBlock_f compressBlock; @@ -907,6 +920,7 @@ typedef struct { int format; U32 windowLog; U32 dictID; + int ldmEnabled; } ZSTD_rust_compressContinueState; size_t ZSTD_rust_compressContinue( const ZSTD_rust_compressContinueState* state, @@ -915,32 +929,35 @@ size_t ZSTD_rust_compressContinue( U32 frame, U32 lastFrameChunk); typedef char ZSTD_rust_compress_continue_state_layout[ (offsetof(ZSTD_rust_compressContinueState, callbackContext) == 0 - && offsetof(ZSTD_rust_compressContinueState, updateWindow) == sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, correctOverflow) == 2 * sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, compressFrameChunk) == 3 * sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, compressBlock) == 4 * sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, stage) == 5 * sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, consumedSrcSize) == 6 * sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, producedCSize) == 7 * sizeof(void*) - && offsetof(ZSTD_rust_compressContinueState, pledgedSrcSizePlusOne) == 8 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, windowState) == sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, ldmWindowState) == 2 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, correctOverflow) == 3 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, compressFrameChunk) == 4 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, compressBlock) == 5 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, stage) == 6 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, consumedSrcSize) == 7 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, producedCSize) == 8 * sizeof(void*) + && offsetof(ZSTD_rust_compressContinueState, pledgedSrcSizePlusOne) == 9 * sizeof(void*) && offsetof(ZSTD_rust_compressContinueState, blockSizeMax) - == 8 * sizeof(void*) + sizeof(U64) + == 9 * sizeof(void*) + sizeof(U64) && offsetof(ZSTD_rust_compressContinueState, checkBlockSize) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) && offsetof(ZSTD_rust_compressContinueState, noDictIDFlag) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + sizeof(int) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + sizeof(int) && offsetof(ZSTD_rust_compressContinueState, checksumFlag) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 2 * sizeof(int) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 2 * sizeof(int) && offsetof(ZSTD_rust_compressContinueState, contentSizeFlag) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 3 * sizeof(int) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 3 * sizeof(int) && offsetof(ZSTD_rust_compressContinueState, format) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 4 * sizeof(int) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 4 * sizeof(int) && offsetof(ZSTD_rust_compressContinueState, windowLog) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) && offsetof(ZSTD_rust_compressContinueState, dictID) - == 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + sizeof(U32) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + sizeof(U32) + && offsetof(ZSTD_rust_compressContinueState, ldmEnabled) + == 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + 2 * sizeof(U32) && sizeof(ZSTD_rust_compressContinueState) - == (sizeof(void*) == 8 ? 112 : 72)) + == (sizeof(void*) == 8 ? 120 : 80)) ? 1 : -1]; /* Rust owns the end-of-frame orchestration. The callbacks retain the @@ -5612,22 +5629,6 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, } -static void ZSTD_rust_compressContinue_updateWindow( - void* context, const void* src, size_t srcSize) -{ - ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; - ZSTD_MatchState_t* const ms = &cctx->blockState.matchState; - - if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) { - ms->forceNonContiguous = 0; - ms->nextToUpdate = ms->window.dictLimit; - } - if (cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) { - ZSTD_window_update(&cctx->ldmState.window, src, srcSize, - /* forceNonContiguous */ 0); - } -} - static void ZSTD_rust_compressContinue_correctOverflow( void* context, const void* src, size_t srcSize) { @@ -5665,8 +5666,30 @@ static size_t ZSTD_compressContinue_dispatch( size_t blockSizeMax, int checkBlockSize) { ZSTD_rust_compressContinueState state; + ZSTD_rust_compressContinueWindowState windowState; + ZSTD_rust_compressContinueWindowState ldmWindowState; + 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; + state.callbackContext = cctx; - state.updateWindow = ZSTD_rust_compressContinue_updateWindow; + state.windowState = &windowState; + state.ldmWindowState = &ldmWindowState; state.correctOverflow = ZSTD_rust_compressContinue_correctOverflow; state.compressFrameChunk = ZSTD_rust_compressContinue_frameChunk; state.compressBlock = ZSTD_rust_compressContinue_block; @@ -5682,6 +5705,7 @@ static size_t ZSTD_compressContinue_dispatch( 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; return ZSTD_rust_compressContinue( &state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk); } diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index 671ef7a31..1b1d92de9 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -795,17 +795,59 @@ type CompressContinueWindowFn = unsafe extern "C" fn(*mut c_void, *const c_void, type CompressContinueBlockFn = unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize; +/// Pointer projection for one C-owned `ZSTD_window_t` and the match-state +/// fields which follow its update. Each field points directly at the C +/// storage so later callbacks observe the updated window immediately. +#[repr(C)] +#[derive(Default)] +struct ZSTD_rust_compressContinueWindowProjection { + next_src: *mut *const c_void, + base: *mut *const c_void, + dict_base: *mut *const c_void, + dict_limit: *mut c_uint, + low_limit: *mut c_uint, + force_non_contiguous: *mut c_int, + next_to_update: *mut c_uint, +} + +const _: () = { + assert!(offset_of!(ZSTD_rust_compressContinueWindowProjection, next_src) == 0); + assert!(offset_of!(ZSTD_rust_compressContinueWindowProjection, base) == size_of::()); + assert!( + offset_of!(ZSTD_rust_compressContinueWindowProjection, dict_base) == 2 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_compressContinueWindowProjection, dict_limit) + == 3 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_compressContinueWindowProjection, low_limit) == 4 * size_of::() + ); + assert!( + offset_of!( + ZSTD_rust_compressContinueWindowProjection, + force_non_contiguous + ) == 5 * size_of::() + ); + assert!( + offset_of!(ZSTD_rust_compressContinueWindowProjection, next_to_update) + == 6 * size_of::() + ); + assert!(size_of::() == 7 * size_of::()); +}; + /// Explicit projection for the high-level continue and deprecated block APIs. /// /// Rust owns stage transitions, frame-header sequencing, input progression, /// and dispatch between the already-migrated frame-chunk/block bodies. The -/// frame-header parameters are projected as scalars, while the opaque callback -/// context remains in C, where callbacks update the private match-state -/// windows and invoke the C-owned context-sensitive operations. +/// frame-header parameters are projected as scalars. The opaque callback +/// context remains in C for overflow correction and context-sensitive block +/// operations; window advancement is projected directly into Rust. #[repr(C)] pub struct ZSTD_rust_compressContinueState { callback_context: *mut c_void, - update_window: CompressContinueWindowFn, + window_state: *const ZSTD_rust_compressContinueWindowProjection, + ldm_window_state: *const ZSTD_rust_compressContinueWindowProjection, correct_overflow: CompressContinueWindowFn, compress_frame_chunk: CompressContinueBlockFn, compress_block: CompressContinueBlockFn, @@ -821,36 +863,40 @@ pub struct ZSTD_rust_compressContinueState { format: c_int, window_log: c_uint, dict_id: c_uint, + ldm_enabled: c_int, } const COMPRESS_CONTINUE_SCALARS_OFFSET: usize = - size_of::<[usize; 8]>() + size_of::() + size_of::(); + size_of::<[usize; 9]>() + size_of::() + size_of::(); const _: () = { assert!(offset_of!(ZSTD_rust_compressContinueState, callback_context) == 0); - assert!(offset_of!(ZSTD_rust_compressContinueState, update_window) == size_of::()); + assert!(offset_of!(ZSTD_rust_compressContinueState, window_state) == size_of::()); assert!( - offset_of!(ZSTD_rust_compressContinueState, correct_overflow) == 2 * size_of::() + offset_of!(ZSTD_rust_compressContinueState, ldm_window_state) == 2 * size_of::() ); assert!( - offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 3 * size_of::() + offset_of!(ZSTD_rust_compressContinueState, correct_overflow) == 3 * size_of::() ); - assert!(offset_of!(ZSTD_rust_compressContinueState, compress_block) == 4 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressContinueState, stage) == 5 * size_of::()); assert!( - offset_of!(ZSTD_rust_compressContinueState, consumed_src_size) == 6 * size_of::() + offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 4 * size_of::() + ); + assert!(offset_of!(ZSTD_rust_compressContinueState, compress_block) == 5 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressContinueState, stage) == 6 * size_of::()); + assert!( + offset_of!(ZSTD_rust_compressContinueState, consumed_src_size) == 7 * size_of::() ); assert!( offset_of!(ZSTD_rust_compressContinueState, produced_c_size) - == 7 * (usize::BITS as usize / 8) + == 8 * (usize::BITS as usize / 8) ); assert!( offset_of!(ZSTD_rust_compressContinueState, pledged_src_size_plus_one) - == size_of::<[usize; 8]>() + == size_of::<[usize; 9]>() ); assert!( offset_of!(ZSTD_rust_compressContinueState, block_size_max) - == size_of::<[usize; 8]>() + size_of::() + == size_of::<[usize; 9]>() + size_of::() ); assert!( offset_of!(ZSTD_rust_compressContinueState, check_block_size) @@ -880,9 +926,13 @@ const _: () = { offset_of!(ZSTD_rust_compressContinueState, dict_id) == COMPRESS_CONTINUE_SCALARS_OFFSET + size_of::<[c_int; 5]>() + size_of::() ); + assert!( + offset_of!(ZSTD_rust_compressContinueState, ldm_enabled) + == COMPRESS_CONTINUE_SCALARS_OFFSET + size_of::<[c_int; 5]>() + 2 * size_of::() + ); assert!( size_of::() - == if size_of::() == 8 { 112 } else { 72 } + == if size_of::() == 8 { 120 } else { 80 } ); }; @@ -890,6 +940,56 @@ const ZSTD_COMPRESSION_STAGE_CREATED: c_int = 0; const ZSTD_COMPRESSION_STAGE_INIT: c_int = 1; const ZSTD_COMPRESSION_STAGE_ONGOING: c_int = 2; +unsafe fn compress_continue_update_window( + projection: *const ZSTD_rust_compressContinueWindowProjection, + src: *const c_void, + src_size: usize, + force_non_contiguous: c_int, + update_match_state: bool, +) -> Result<(), usize> { + if projection.is_null() { + return Err(ERROR(ZstdErrorCode::Generic)); + } + let projection = unsafe { &*projection }; + if projection.next_src.is_null() + || projection.base.is_null() + || projection.dict_base.is_null() + || projection.dict_limit.is_null() + || projection.low_limit.is_null() + { + return Err(ERROR(ZstdErrorCode::Generic)); + } + if update_match_state + && (projection.force_non_contiguous.is_null() || projection.next_to_update.is_null()) + { + return Err(ERROR(ZstdErrorCode::Generic)); + } + + let mut window_state = ZSTD_rust_windowUpdateState { + nextSrc: unsafe { *projection.next_src }, + base: unsafe { *projection.base }, + dictBase: unsafe { *projection.dict_base }, + dictLimit: unsafe { *projection.dict_limit }, + lowLimit: unsafe { *projection.low_limit }, + }; + let contiguous = + unsafe { ZSTD_rust_windowUpdate(&mut window_state, src, src_size, force_non_contiguous) }; + unsafe { + *projection.next_src = window_state.nextSrc; + *projection.base = window_state.base; + *projection.dict_base = window_state.dictBase; + *projection.dict_limit = window_state.dictLimit; + *projection.low_limit = window_state.lowLimit; + } + if update_match_state && contiguous == 0 { + unsafe { + *projection.force_non_contiguous = 0; + *projection.next_to_update = window_state.dictLimit; + } + } + Ok(()) +} + #[allow(clippy::too_many_arguments)] unsafe fn compress_continue_body_with( state: &ZSTD_rust_compressContinueState, @@ -947,7 +1047,32 @@ unsafe fn compress_continue_body_with( return frame_header_size; } - unsafe { (state.update_window)(state.callback_context, src, src_size) }; + if state.window_state.is_null() { + return ERROR(ZstdErrorCode::Generic); + } + let match_window = unsafe { &*state.window_state }; + if match_window.force_non_contiguous.is_null() { + return ERROR(ZstdErrorCode::Generic); + } + let force_non_contiguous = unsafe { *match_window.force_non_contiguous }; + if let Err(result) = unsafe { + compress_continue_update_window( + state.window_state, + src, + src_size, + force_non_contiguous, + true, + ) + } { + return result; + } + if state.ldm_enabled != 0 { + if let Err(result) = unsafe { + compress_continue_update_window(state.ldm_window_state, src, src_size, 0, false) + } { + return result; + } + } if frame == 0 { unsafe { (state.correct_overflow)(state.callback_context, src, src_size) }; } @@ -7610,7 +7735,7 @@ const HASH_READ_SIZE: u32 = 8; /// Pointer arithmetic is intentionally performed as wrapping address math to /// mirror the original C implementation's pointer-overflow contract. #[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct ZSTD_rust_windowUpdateState { pub nextSrc: *const c_void, pub base: *const c_void, @@ -11026,13 +11151,18 @@ mod tests { #[derive(Default)] struct CompressContinueTestContext { - update_window_calls: usize, overflow_calls: usize, frame_calls: usize, block_calls: usize, last_frame_chunk: c_uint, frame_result: usize, block_result: usize, + window: ZSTD_rust_windowUpdateState, + ldm_window: ZSTD_rust_windowUpdateState, + force_non_contiguous: c_int, + next_to_update: c_uint, + window_projection: ZSTD_rust_compressContinueWindowProjection, + ldm_window_projection: ZSTD_rust_compressContinueWindowProjection, } unsafe fn compress_continue_test_context( @@ -11041,15 +11171,6 @@ mod tests { unsafe { &mut *context.cast::() } } - unsafe extern "C" fn compress_continue_test_window( - context: *mut c_void, - _src: *const c_void, - _src_size: usize, - ) { - let context = unsafe { compress_continue_test_context(context) }; - context.update_window_calls += 1; - } - unsafe extern "C" fn compress_continue_test_overflow( context: *mut c_void, _src: *const c_void, @@ -11095,9 +11216,40 @@ mod tests { block_size_max: usize, check_block_size: c_int, ) -> ZSTD_rust_compressContinueState { + let base = WINDOW_INIT_SENTINEL.as_ptr().cast::(); + let next_src = unsafe { base.cast::().add(2).cast::() }; + context.window = ZSTD_rust_windowUpdateState { + nextSrc: next_src, + base, + dictBase: base, + dictLimit: ZSTD_WINDOW_START_INDEX, + lowLimit: ZSTD_WINDOW_START_INDEX, + }; + context.ldm_window = context.window; + context.force_non_contiguous = 0; + context.next_to_update = ZSTD_WINDOW_START_INDEX; + 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), + }; + context.ldm_window_projection = ZSTD_rust_compressContinueWindowProjection { + next_src: ptr::addr_of_mut!(context.ldm_window.nextSrc), + base: ptr::addr_of_mut!(context.ldm_window.base), + dict_base: ptr::addr_of_mut!(context.ldm_window.dictBase), + dict_limit: ptr::addr_of_mut!(context.ldm_window.dictLimit), + low_limit: ptr::addr_of_mut!(context.ldm_window.lowLimit), + force_non_contiguous: ptr::null_mut(), + next_to_update: ptr::null_mut(), + }; ZSTD_rust_compressContinueState { callback_context: (context as *mut CompressContinueTestContext).cast(), - update_window: compress_continue_test_window, + window_state: &context.window_projection, + ldm_window_state: &context.ldm_window_projection, correct_overflow: compress_continue_test_overflow, compress_frame_chunk: compress_continue_test_frame, compress_block: compress_continue_test_block, @@ -11113,6 +11265,7 @@ mod tests { format: 0, window_log: 10, dict_id: 0, + ldm_enabled: 1, } } @@ -11153,7 +11306,12 @@ mod tests { assert_eq!(stage, ZSTD_COMPRESSION_STAGE_ONGOING); assert_eq!(consumed, 12); assert_eq!(produced, 23); - assert_eq!(context.update_window_calls, 1); + assert_eq!(context.window.nextSrc, unsafe { + source.as_ptr().add(source.len()).cast() + }); + assert_eq!(context.ldm_window.nextSrc, context.window.nextSrc); + assert_eq!(context.force_non_contiguous, 0); + assert_eq!(context.next_to_update, context.window.dictLimit); assert_eq!(context.overflow_calls, 0); assert_eq!(context.frame_calls, 1); assert_eq!(context.block_calls, 0); @@ -11192,7 +11350,6 @@ mod tests { assert_eq!(result, 6); assert_eq!(stage, ZSTD_COMPRESSION_STAGE_ONGOING); assert_eq!((consumed, produced), (7, 11)); - assert_eq!(context.update_window_calls, 0); assert_eq!(context.frame_calls, 0); assert_eq!(&output[..6], &[0x28, 0xb5, 0x2f, 0xfd, 0x00, 0x00]); assert_eq!(&output[6..], &[0xa5; 12]); @@ -11215,6 +11372,8 @@ mod tests { ); let source = [0x22u8; 5]; let mut output = [0xa5u8; 16]; + let initial_window = context.window; + let initial_ldm_window = context.ldm_window; let oversized = unsafe { ZSTD_rust_compressContinue( @@ -11230,7 +11389,8 @@ mod tests { assert_eq!(oversized, ERROR(ZstdErrorCode::SrcSizeWrong)); assert_eq!(stage, ZSTD_COMPRESSION_STAGE_INIT); assert_eq!((consumed, produced), (4, 9)); - assert_eq!(context.update_window_calls, 0); + assert_eq!(context.window, initial_window); + assert_eq!(context.ldm_window, initial_ldm_window); assert_eq!(context.block_calls, 0); state.check_block_size = 0; @@ -11248,7 +11408,8 @@ mod tests { }; assert_eq!(created, ERROR(ZstdErrorCode::StageWrong)); assert_eq!(stage, ZSTD_COMPRESSION_STAGE_CREATED); - assert_eq!(context.update_window_calls, 0); + assert_eq!(context.window, initial_window); + assert_eq!(context.ldm_window, initial_ldm_window); assert_eq!(context.block_calls, 0); } @@ -11290,7 +11451,10 @@ mod tests { (stage, consumed, produced), (ZSTD_COMPRESSION_STAGE_ONGOING, 4, 9) ); - assert_eq!(context.update_window_calls, 1); + assert_eq!(context.window.nextSrc, unsafe { + source.as_ptr().add(source.len()).cast() + }); + assert_eq!(context.ldm_window.nextSrc, context.window.nextSrc); assert_eq!(context.overflow_calls, 1); assert_eq!(context.block_calls, 1); } @@ -11330,6 +11494,9 @@ mod tests { assert_eq!(result, ERROR(ZstdErrorCode::SrcSizeWrong)); assert_eq!((consumed, produced), (6, 3)); + assert_eq!(context.window.nextSrc, unsafe { + source.as_ptr().add(source.len()).cast() + }); assert_eq!(context.block_calls, 1); }