feat(compress): project continue overflow correction into Rust

Pass the existing overflow-correction projection directly through the
compressContinue ABI so Rust owns the correction decision and ordering while
C retains only the table/workspace callbacks. Remove the redundant C
forwarding adapter and keep the stack projection valid for synchronous
dispatch.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --all -- --check
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --lib zstd_compress::tests::compress_continue -- --nocapture
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --all-targets -- -D warnings
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s
- ulimit -v 41943040; make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
This commit is contained in:
2026-07-20 00:40:55 +02:00
parent 30c5bc9f90
commit 3ec8f03850
2 changed files with 69 additions and 30 deletions
+51 -13
View File
@@ -793,7 +793,6 @@ pub unsafe extern "C" fn ZSTD_rust_compressFrameChunk(
}
}
type CompressContinueWindowFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
type CompressContinueBlockFn =
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize;
@@ -843,14 +842,14 @@ const _: () = {
/// 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. The opaque callback
/// context remains in C for overflow correction and context-sensitive block
/// operations; window advancement is projected directly into Rust.
/// context remains in C for overflow-correction callbacks and context-sensitive
/// block operations; window advancement is projected directly into Rust.
#[repr(C)]
pub struct ZSTD_rust_compressContinueState {
callback_context: *mut c_void,
window_state: *const ZSTD_rust_compressContinueWindowProjection,
ldm_window_state: *const ZSTD_rust_compressContinueWindowProjection,
correct_overflow: CompressContinueWindowFn,
overflow_state: *const ZSTD_rust_overflowCorrectState,
compress_frame_chunk: CompressContinueBlockFn,
compress_block: CompressContinueBlockFn,
stage: *mut c_int,
@@ -877,9 +876,7 @@ const _: () = {
assert!(
offset_of!(ZSTD_rust_compressContinueState, ldm_window_state) == 2 * size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_compressContinueState, correct_overflow) == 3 * size_of::<usize>()
);
assert!(offset_of!(ZSTD_rust_compressContinueState, overflow_state) == 3 * size_of::<usize>());
assert!(
offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 4 * size_of::<usize>()
);
@@ -1076,7 +1073,11 @@ unsafe fn compress_continue_body_with(
}
}
if frame == 0 {
unsafe { (state.correct_overflow)(state.callback_context, src, src_size) };
if state.overflow_state.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
let src_end = src.cast::<u8>().wrapping_add(src_size).cast();
unsafe { ZSTD_rust_overflowCorrectIfNeeded(state.overflow_state, src, src_end) };
}
let compressed_size = if frame != 0 {
@@ -11168,8 +11169,11 @@ mod tests {
ldm_window: ZSTD_rust_windowUpdateState,
force_non_contiguous: c_int,
next_to_update: c_uint,
loaded_dict_end: c_uint,
dict_match_state: *const c_void,
window_projection: ZSTD_rust_compressContinueWindowProjection,
ldm_window_projection: ZSTD_rust_compressContinueWindowProjection,
overflow_state: Option<ZSTD_rust_overflowCorrectState>,
}
unsafe fn compress_continue_test_context(
@@ -11178,13 +11182,29 @@ mod tests {
unsafe { &mut *context.cast::<CompressContinueTestContext>() }
}
unsafe extern "C" fn compress_continue_test_overflow(
unsafe extern "C" fn compress_continue_test_overflow_need(
context: *mut c_void,
_src: *const c_void,
_src_size: usize,
) {
_src_end: *const c_void,
) -> c_int {
let context = unsafe { compress_continue_test_context(context) };
context.overflow_calls += 1;
0
}
unsafe extern "C" fn compress_continue_test_overflow_correct(
_context: *mut c_void,
_src: *const c_void,
) -> c_uint {
0
}
unsafe extern "C" fn compress_continue_test_overflow_callback(_context: *mut c_void) {}
unsafe extern "C" fn compress_continue_test_overflow_reduce(
_context: *mut c_void,
_correction: c_uint,
) {
}
unsafe extern "C" fn compress_continue_test_frame(
@@ -11235,6 +11255,8 @@ mod tests {
context.ldm_window = context.window;
context.force_non_contiguous = 0;
context.next_to_update = ZSTD_WINDOW_START_INDEX;
context.loaded_dict_end = 0;
context.dict_match_state = ptr::null();
context.window_projection = ZSTD_rust_compressContinueWindowProjection {
next_src: ptr::addr_of_mut!(context.window.nextSrc),
base: ptr::addr_of_mut!(context.window.base),
@@ -11253,11 +11275,27 @@ mod tests {
force_non_contiguous: ptr::null_mut(),
next_to_update: ptr::null_mut(),
};
let callback_context = (context as *mut CompressContinueTestContext).cast();
context.overflow_state = Some(ZSTD_rust_overflowCorrectState {
callback_context,
next_to_update: ptr::addr_of_mut!(context.next_to_update),
need_correction: Some(compress_continue_test_overflow_need),
correct_overflow: Some(compress_continue_test_overflow_correct),
mark_tables_dirty: Some(compress_continue_test_overflow_callback),
reduce_index: Some(compress_continue_test_overflow_reduce),
mark_tables_clean: Some(compress_continue_test_overflow_callback),
loaded_dict_end: ptr::addr_of_mut!(context.loaded_dict_end),
dict_match_state: ptr::addr_of_mut!(context.dict_match_state),
});
let overflow_state = context
.overflow_state
.as_ref()
.map_or(ptr::null(), |state| state as *const _);
ZSTD_rust_compressContinueState {
callback_context: (context as *mut CompressContinueTestContext).cast(),
callback_context,
window_state: &context.window_projection,
ldm_window_state: &context.ldm_window_projection,
correct_overflow: compress_continue_test_overflow,
overflow_state,
compress_frame_chunk: compress_continue_test_frame,
compress_block: compress_continue_test_block,
stage,