feat(compress): call reset storage policy directly from Rust

The CCtx reset tail already delegated storage reservation and ordering policy
to Rust, but crossed back into C through a redundant callback trampoline.
Project the storage state directly through the existing pointer-sized ABI slot
and invoke the Rust storage operation without the extra C hop. Keep private
workspace/layout callbacks and match-state reset in C, preserve hash -> match
-> storage ordering, and retain allocation-error propagation in Rust tests.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo check --manifest-path rust/Cargo.toml --tests
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; make -j1 -C tests test
This commit is contained in:
2026-07-21 19:30:01 +02:00
parent 8c20f95010
commit 5f965b7025
2 changed files with 111 additions and 24 deletions
+108 -14
View File
@@ -9930,15 +9930,15 @@ const _: () = {
/// C-owned operations used by the post-workspace CCtx reset tail.
///
/// Rust owns the operation order, compressed-block reset, and error
/// propagation. C retains the private context initialization, match-state
/// reset, and storage publication operations.
/// propagation. C retains the private context initialization and match-state
/// reset; the storage policy is called directly through its projected state.
#[repr(C)]
pub struct ZSTD_rust_resetCCtxTailState {
callbackContext: *mut c_void,
resetHash: Option<ResetCCtxStorageCallback>,
compressedBlockState: *mut ZSTD_compressedBlockState_t,
resetMatchState: Option<ResetCCtxTailCallback>,
resetStorage: Option<ResetCCtxTailCallback>,
storageState: *const ZSTD_rust_resetCCtxStorageState,
matchStateCParams: *mut ZSTD_compressionParameters,
matchStatePrefetchCDictTables: *mut c_int,
pledgedSrcSizePlusOne: *mut u64,
@@ -9962,7 +9962,7 @@ const _: () = {
offset_of!(ZSTD_rust_resetCCtxTailState, compressedBlockState) == 2 * size_of::<usize>()
);
assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetMatchState) == 3 * size_of::<usize>());
assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetStorage) == 4 * size_of::<usize>());
assert!(offset_of!(ZSTD_rust_resetCCtxTailState, storageState) == 4 * size_of::<usize>());
assert!(
offset_of!(ZSTD_rust_resetCCtxTailState, matchStateCParams) == 5 * size_of::<usize>()
);
@@ -10462,9 +10462,9 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxTail(
let Some(reset_match_state) = state.resetMatchState else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(reset_storage) = state.resetStorage else {
if state.storageState.is_null() {
return ERROR(ZstdErrorCode::Generic);
};
}
if state.compressedBlockState.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
@@ -10502,7 +10502,7 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxTail(
if ERR_isError(result) {
return result;
}
let result = reset_storage(state.callbackContext);
let result = ZSTD_rust_resetCCtxStorage(state.storageState);
if ERR_isError(result) {
return result;
}
@@ -23436,6 +23436,8 @@ mod tests {
#[derive(Default)]
struct ResetCCtxTailTestContext {
events: Vec<&'static str>,
storage_allocations: Vec<Box<[u8]>>,
storage_error_armed: bool,
match_result: usize,
storage_result: usize,
c_params: ZSTD_compressionParameters,
@@ -23471,22 +23473,110 @@ mod tests {
context.match_result
}
unsafe extern "C" fn reset_cctx_tail_test_reset_storage(context: *mut c_void) -> usize {
unsafe extern "C" fn reset_cctx_tail_storage_set_pointer(
_context: *mut c_void,
_pointer_kind: c_int,
_pointer: *mut c_void,
) {
}
unsafe extern "C" fn reset_cctx_tail_storage_set_size(
_context: *mut c_void,
_size_kind: c_int,
_value: usize,
) {
}
unsafe extern "C" fn reset_cctx_tail_storage_set_int(
_context: *mut c_void,
_int_kind: c_int,
_value: c_int,
) {
}
unsafe extern "C" fn reset_cctx_tail_storage_reserve(
context: *mut c_void,
_reserve_kind: c_int,
size: usize,
) -> *mut c_void {
let context = unsafe { reset_cctx_tail_test_context(context) };
let allocation = vec![0u8; size.max(1)].into_boxed_slice();
let pointer = allocation.as_ptr() as *mut c_void;
context.storage_allocations.push(allocation);
pointer
}
unsafe extern "C" fn reset_cctx_tail_storage_reserve_failed(
context: *mut c_void,
) -> c_int {
let context = unsafe { reset_cctx_tail_test_context(context) };
c_int::from(context.storage_error_armed)
}
unsafe extern "C" fn reset_cctx_tail_storage_zero(
_context: *mut c_void,
pointer: *mut c_void,
size: usize,
) {
if !pointer.is_null() {
unsafe { ptr::write_bytes(pointer.cast::<u8>(), 0, size) };
}
}
unsafe extern "C" fn reset_cctx_tail_storage_window_init(_context: *mut c_void) {}
unsafe extern "C" fn reset_cctx_tail_storage_reset_external_sequences(
context: *mut c_void,
) {
let context = unsafe { reset_cctx_tail_test_context(context) };
context.events.push("reset-storage");
context.storage_result
context.storage_error_armed = context.storage_result != 0;
}
fn reset_cctx_tail_test_storage_state(
context: &mut ResetCCtxTailTestContext,
) -> ZSTD_rust_resetCCtxStorageState {
ZSTD_rust_resetCCtxStorageState {
callbackContext: (context as *mut ResetCCtxTailTestContext).cast(),
ldmEnable: ZSTD_RUST_PS_DISABLE,
hasExtSeqProd: 0,
hashLog: 0,
bucketSizeLog: 0,
blockSize: 1,
maxNbSeq: 1,
maxNbLdmSeq: 0,
maxNbExternalSeq: 0,
buffInSize: 0,
buffOutSize: 0,
seqDefSize: 1,
ldmEntrySize: 1,
rawSeqSize: 1,
externalSequenceSize: 1,
byteSize: 1,
wildcopyOverlength: 0,
bufferedPolicy: 0,
setPointer: Some(reset_cctx_tail_storage_set_pointer),
setSize: Some(reset_cctx_tail_storage_set_size),
setInt: Some(reset_cctx_tail_storage_set_int),
reserve: Some(reset_cctx_tail_storage_reserve),
reserveFailed: Some(reset_cctx_tail_storage_reserve_failed),
zero: Some(reset_cctx_tail_storage_zero),
windowInit: Some(reset_cctx_tail_storage_window_init),
resetExternalSequences: Some(reset_cctx_tail_storage_reset_external_sequences),
}
}
fn reset_cctx_tail_test_state(
context: &mut ResetCCtxTailTestContext,
compressed_block_state: *mut ZSTD_compressedBlockState_t,
storage_state: &mut ZSTD_rust_resetCCtxStorageState,
) -> ZSTD_rust_resetCCtxTailState {
ZSTD_rust_resetCCtxTailState {
callbackContext: (context as *mut ResetCCtxTailTestContext).cast(),
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),
storageState: storage_state,
matchStateCParams: ptr::addr_of_mut!(context.match_state_cparams),
matchStatePrefetchCDictTables: ptr::addr_of_mut!(
context.match_state_prefetch_cdict_tables
@@ -23511,7 +23601,8 @@ mod tests {
let mut context = ResetCCtxTailTestContext::default();
let mut block_state =
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
assert_eq!(unsafe { ZSTD_rust_resetCCtxTail(&state) }, 0);
assert_eq!(
@@ -23551,7 +23642,8 @@ mod tests {
};
let mut block_state =
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
assert_eq!(unsafe { ZSTD_rust_resetCCtxTail(&state) }, 0);
assert_eq!(context.match_state_cparams, c_params);
@@ -23574,7 +23666,8 @@ mod tests {
};
let mut block_state =
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
assert_eq!(
unsafe { ZSTD_rust_resetCCtxTail(&state) },
@@ -23591,7 +23684,8 @@ mod tests {
};
let mut block_state =
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
assert_eq!(
unsafe { ZSTD_rust_resetCCtxTail(&state) },