feat(compress): move CCtx reset storage policy into Rust

Move the post-match-state CCtx storage reservation and publication policy into
Rust while keeping the private C workspace and context layouts behind narrow
callbacks. The Rust leaf now preserves the sequence, LDM, external-sequence,
literal, buffered-input/output, bucket, and entropy-code allocation order,
including zeroing and reset callbacks. C remains responsible for workspace
resize/layout, private field publication, allocator callbacks, and the LDM
window reset details. ABI layout assertions and fake-callback tests cover
ordinary, LDM/external-producer, and allocation-failure paths.

Test Plan:
- ulimit -v 41943040 && CARGO_BUILD_JOBS=1 cargo fmt --manifest-path rust/Cargo.toml
- ulimit -v 41943040 && CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml cctx_storage --lib (3 passed)
- ulimit -v 41943040 && CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --lib (683 passed)
- ulimit -v 41943040 && CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040 && make -B -C programs -j1 zstd (passed; existing fileio const-cast warnings)
- ulimit -v 41943040 && make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s (84 tests and both short fuzz rounds passed; existing zstreamtest warning)
This commit is contained in:
2026-07-19 18:16:44 +02:00
parent 853792f2c4
commit db8c58ac97
3 changed files with 930 additions and 57 deletions
+634
View File
@@ -6020,6 +6020,363 @@ pub unsafe extern "C" fn ZSTD_rust_planCCtxReset(state: *const ZSTD_rustCCtxRese
0
}
type ResetCCtxStorageSetPointer = unsafe extern "C" fn(*mut c_void, c_int, *mut c_void);
type ResetCCtxStorageSetSize = unsafe extern "C" fn(*mut c_void, c_int, usize);
type ResetCCtxStorageSetInt = unsafe extern "C" fn(*mut c_void, c_int, c_int);
type ResetCCtxStorageReserve = unsafe extern "C" fn(*mut c_void, c_int, usize) -> *mut c_void;
type ResetCCtxStorageReserveFailed = unsafe extern "C" fn(*mut c_void) -> c_int;
type ResetCCtxStorageZero = unsafe extern "C" fn(*mut c_void, *mut c_void, usize);
type ResetCCtxStorageCallback = unsafe extern "C" fn(*mut c_void);
const RESET_CCTX_RESERVE_ALIGNED64: c_int = 0;
const RESET_CCTX_RESERVE_BUFFER: c_int = 1;
const RESET_CCTX_POINTER_SEQ_START: c_int = 0;
const RESET_CCTX_POINTER_LDM_HASH: c_int = 1;
const RESET_CCTX_POINTER_LDM_SEQUENCES: c_int = 2;
const RESET_CCTX_POINTER_EXTERNAL_SEQUENCES: c_int = 3;
const RESET_CCTX_POINTER_LITERALS: c_int = 4;
const RESET_CCTX_POINTER_INPUT_BUFFER: c_int = 5;
const RESET_CCTX_POINTER_OUTPUT_BUFFER: c_int = 6;
const RESET_CCTX_POINTER_LL_CODE: c_int = 7;
const RESET_CCTX_POINTER_ML_CODE: c_int = 8;
const RESET_CCTX_POINTER_OF_CODE: c_int = 9;
const RESET_CCTX_POINTER_LDM_BUCKETS: c_int = 10;
const RESET_CCTX_SIZE_MAX_NB_SEQ: c_int = 0;
const RESET_CCTX_SIZE_MAX_NB_LIT: c_int = 1;
const RESET_CCTX_SIZE_MAX_NB_LDM_SEQ: c_int = 2;
const RESET_CCTX_SIZE_EXTERNAL_SEQ_CAPACITY: c_int = 3;
const RESET_CCTX_SIZE_INPUT_BUFFER: c_int = 4;
const RESET_CCTX_SIZE_OUTPUT_BUFFER: c_int = 5;
const RESET_CCTX_INT_BUFFERED_POLICY: c_int = 0;
const RESET_CCTX_INT_INITIALIZED: c_int = 1;
/// C-owned workspace/layout projection for the post-match-state reset tail.
///
/// Rust owns the reservation order and size policy. C retains the private
/// `ZSTD_CCtx`/`ldmState_t` layouts and implements the workspace callbacks.
#[repr(C)]
pub struct ZSTD_rust_resetCCtxStorageState {
pub callbackContext: *mut c_void,
pub ldmEnable: c_int,
pub hasExtSeqProd: c_int,
pub hashLog: c_uint,
pub bucketSizeLog: c_uint,
pub blockSize: usize,
pub maxNbSeq: usize,
pub maxNbLdmSeq: usize,
pub maxNbExternalSeq: usize,
pub buffInSize: usize,
pub buffOutSize: usize,
pub seqDefSize: usize,
pub ldmEntrySize: usize,
pub rawSeqSize: usize,
pub externalSequenceSize: usize,
pub byteSize: usize,
pub wildcopyOverlength: usize,
pub bufferedPolicy: c_int,
pub setPointer: Option<ResetCCtxStorageSetPointer>,
pub setSize: Option<ResetCCtxStorageSetSize>,
pub setInt: Option<ResetCCtxStorageSetInt>,
pub reserve: Option<ResetCCtxStorageReserve>,
pub reserveFailed: Option<ResetCCtxStorageReserveFailed>,
pub zero: Option<ResetCCtxStorageZero>,
pub windowInit: Option<ResetCCtxStorageCallback>,
pub resetExternalSequences: Option<ResetCCtxStorageCallback>,
}
const _: () = {
assert!(size_of::<ResetCCtxStorageSetPointer>() == size_of::<usize>());
assert!(size_of::<ResetCCtxStorageSetSize>() == size_of::<usize>());
assert!(size_of::<ResetCCtxStorageSetInt>() == size_of::<usize>());
assert!(size_of::<ResetCCtxStorageReserve>() == size_of::<usize>());
assert!(size_of::<ResetCCtxStorageReserveFailed>() == size_of::<usize>());
assert!(size_of::<ResetCCtxStorageZero>() == size_of::<usize>());
assert!(size_of::<ResetCCtxStorageCallback>() == size_of::<usize>());
assert!(offset_of!(ZSTD_rust_resetCCtxStorageState, callbackContext) == 0);
assert!(offset_of!(ZSTD_rust_resetCCtxStorageState, ldmEnable) == size_of::<usize>());
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, hasExtSeqProd)
== size_of::<usize>() + size_of::<c_int>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, hashLog)
> offset_of!(ZSTD_rust_resetCCtxStorageState, hasExtSeqProd)
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, bucketSizeLog)
== offset_of!(ZSTD_rust_resetCCtxStorageState, hashLog) + size_of::<c_uint>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, blockSize)
> offset_of!(ZSTD_rust_resetCCtxStorageState, bucketSizeLog)
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, maxNbSeq)
== offset_of!(ZSTD_rust_resetCCtxStorageState, blockSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, maxNbLdmSeq)
== offset_of!(ZSTD_rust_resetCCtxStorageState, maxNbSeq) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, maxNbExternalSeq)
== offset_of!(ZSTD_rust_resetCCtxStorageState, maxNbLdmSeq) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, buffInSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, maxNbExternalSeq) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, buffOutSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, buffInSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, seqDefSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, buffOutSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, ldmEntrySize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, seqDefSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, rawSeqSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, ldmEntrySize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, externalSequenceSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, rawSeqSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, byteSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, externalSequenceSize)
+ size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, wildcopyOverlength)
== offset_of!(ZSTD_rust_resetCCtxStorageState, byteSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, bufferedPolicy)
> offset_of!(ZSTD_rust_resetCCtxStorageState, wildcopyOverlength)
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, setSize)
== offset_of!(ZSTD_rust_resetCCtxStorageState, setPointer) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, setInt)
== offset_of!(ZSTD_rust_resetCCtxStorageState, setSize) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetCCtxStorageState, reserve)
== offset_of!(ZSTD_rust_resetCCtxStorageState, setInt) + size_of::<usize>()
);
assert!(
size_of::<ZSTD_rust_resetCCtxStorageState>()
== offset_of!(ZSTD_rust_resetCCtxStorageState, resetExternalSequences)
+ size_of::<usize>()
);
};
/// Reserve and publish the private CCtx storage that follows match-state reset.
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_resetCCtxStorage(
state: *const ZSTD_rust_resetCCtxStorageState,
) -> usize {
if state.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
let state = unsafe { &*state };
if state.callbackContext.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
let Some(set_pointer) = state.setPointer else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(set_size) = state.setSize else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(set_int) = state.setInt else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(reserve_callback) = state.reserve else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(reserve_failed) = state.reserveFailed else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(zero) = state.zero else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(window_init) = state.windowInit else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(reset_external_sequences) = state.resetExternalSequences else {
return ERROR(ZstdErrorCode::Generic);
};
let reserve = |kind: c_int, size: usize| -> Result<*mut c_void, usize> {
let pointer = unsafe { reserve_callback(state.callbackContext, kind, size) };
if unsafe { reserve_failed(state.callbackContext) } != 0 {
Err(ERROR(ZstdErrorCode::MemoryAllocation))
} else {
Ok(pointer)
}
};
let publish_pointer = |kind: c_int, pointer: *mut c_void| unsafe {
set_pointer(state.callbackContext, kind, pointer)
};
let publish_size =
|kind: c_int, value: usize| unsafe { set_size(state.callbackContext, kind, value) };
let sequence_start = match reserve(
RESET_CCTX_RESERVE_ALIGNED64,
state.maxNbSeq.wrapping_mul(state.seqDefSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_SEQ_START, sequence_start);
if state.ldmEnable == ZSTD_RUST_PS_ENABLE {
if state.bucketSizeLog > state.hashLog {
return ERROR(ZstdErrorCode::Generic);
}
let Some(hash_size) = 1usize.checked_shl(state.hashLog) else {
return ERROR(ZstdErrorCode::Generic);
};
let hash_table = match reserve(
RESET_CCTX_RESERVE_ALIGNED64,
hash_size.wrapping_mul(state.ldmEntrySize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_LDM_HASH, hash_table);
unsafe {
zero(
state.callbackContext,
hash_table,
hash_size.wrapping_mul(state.ldmEntrySize),
)
};
let ldm_sequences = match reserve(
RESET_CCTX_RESERVE_ALIGNED64,
state.maxNbLdmSeq.wrapping_mul(state.rawSeqSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_LDM_SEQUENCES, ldm_sequences);
publish_size(RESET_CCTX_SIZE_MAX_NB_LDM_SEQ, state.maxNbLdmSeq);
unsafe { window_init(state.callbackContext) };
}
if state.hasExtSeqProd != 0 {
let external_sequences = match reserve(
RESET_CCTX_RESERVE_ALIGNED64,
state
.maxNbExternalSeq
.wrapping_mul(state.externalSequenceSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_EXTERNAL_SEQUENCES, external_sequences);
publish_size(
RESET_CCTX_SIZE_EXTERNAL_SEQ_CAPACITY,
state.maxNbExternalSeq,
);
}
let literals = match reserve(
RESET_CCTX_RESERVE_BUFFER,
state.blockSize.wrapping_add(state.wildcopyOverlength),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_LITERALS, literals);
publish_size(RESET_CCTX_SIZE_MAX_NB_LIT, state.blockSize);
unsafe {
set_int(
state.callbackContext,
RESET_CCTX_INT_BUFFERED_POLICY,
state.bufferedPolicy,
)
};
let input_buffer = match reserve(RESET_CCTX_RESERVE_BUFFER, state.buffInSize) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_INPUT_BUFFER, input_buffer);
publish_size(RESET_CCTX_SIZE_INPUT_BUFFER, state.buffInSize);
let output_buffer = match reserve(RESET_CCTX_RESERVE_BUFFER, state.buffOutSize) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_OUTPUT_BUFFER, output_buffer);
publish_size(RESET_CCTX_SIZE_OUTPUT_BUFFER, state.buffOutSize);
if state.ldmEnable == ZSTD_RUST_PS_ENABLE {
let bucket_count = match 1usize.checked_shl(state.hashLog - state.bucketSizeLog) {
Some(count) => count,
None => return ERROR(ZstdErrorCode::Generic),
};
let bucket_offsets = match reserve(
RESET_CCTX_RESERVE_BUFFER,
bucket_count.wrapping_mul(state.byteSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_LDM_BUCKETS, bucket_offsets);
unsafe {
zero(
state.callbackContext,
bucket_offsets,
bucket_count.wrapping_mul(state.byteSize),
)
};
}
unsafe { reset_external_sequences(state.callbackContext) };
publish_size(RESET_CCTX_SIZE_MAX_NB_SEQ, state.maxNbSeq);
let ll_code = match reserve(
RESET_CCTX_RESERVE_BUFFER,
state.maxNbSeq.wrapping_mul(state.byteSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_LL_CODE, ll_code);
let ml_code = match reserve(
RESET_CCTX_RESERVE_BUFFER,
state.maxNbSeq.wrapping_mul(state.byteSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_ML_CODE, ml_code);
let of_code = match reserve(
RESET_CCTX_RESERVE_BUFFER,
state.maxNbSeq.wrapping_mul(state.byteSize),
) {
Ok(pointer) => pointer,
Err(error) => return error,
};
publish_pointer(RESET_CCTX_POINTER_OF_CODE, of_code);
unsafe { set_int(state.callbackContext, RESET_CCTX_INT_INITIALIZED, 1) };
0
}
#[inline]
fn max_estimate_cctx_size(
estimate0: usize,
@@ -13975,6 +14332,283 @@ mod tests {
);
}
#[derive(Debug, PartialEq)]
enum ResetCCtxStorageTestEvent {
Reserve(c_int, usize),
Pointer(c_int),
Size(c_int, usize),
Int(c_int, c_int),
Zero(usize),
WindowInit,
ResetExternalSequences,
}
#[derive(Default)]
struct ResetCCtxStorageTestContext {
events: Vec<ResetCCtxStorageTestEvent>,
reserve_count: usize,
reserve_failure: bool,
}
unsafe fn reset_cctx_storage_test_context(
context: *mut c_void,
) -> &'static mut ResetCCtxStorageTestContext {
unsafe { &mut *context.cast::<ResetCCtxStorageTestContext>() }
}
unsafe extern "C" fn reset_cctx_storage_test_set_pointer(
context: *mut c_void,
kind: c_int,
_pointer: *mut c_void,
) {
let context = unsafe { reset_cctx_storage_test_context(context) };
context
.events
.push(ResetCCtxStorageTestEvent::Pointer(kind));
}
unsafe extern "C" fn reset_cctx_storage_test_set_size(
context: *mut c_void,
kind: c_int,
value: usize,
) {
let context = unsafe { reset_cctx_storage_test_context(context) };
context
.events
.push(ResetCCtxStorageTestEvent::Size(kind, value));
}
unsafe extern "C" fn reset_cctx_storage_test_set_int(
context: *mut c_void,
kind: c_int,
value: c_int,
) {
let context = unsafe { reset_cctx_storage_test_context(context) };
context
.events
.push(ResetCCtxStorageTestEvent::Int(kind, value));
}
unsafe extern "C" fn reset_cctx_storage_test_reserve(
context: *mut c_void,
kind: c_int,
size: usize,
) -> *mut c_void {
let context = unsafe { reset_cctx_storage_test_context(context) };
context
.events
.push(ResetCCtxStorageTestEvent::Reserve(kind, size));
let pointer = (0x1000usize + context.reserve_count * 0x1000) as *mut c_void;
context.reserve_count += 1;
pointer
}
unsafe extern "C" fn reset_cctx_storage_test_reserve_failed(context: *mut c_void) -> c_int {
let context = unsafe { reset_cctx_storage_test_context(context) };
c_int::from(context.reserve_failure)
}
unsafe extern "C" fn reset_cctx_storage_test_zero(
context: *mut c_void,
_pointer: *mut c_void,
size: usize,
) {
let context = unsafe { reset_cctx_storage_test_context(context) };
context.events.push(ResetCCtxStorageTestEvent::Zero(size));
}
unsafe extern "C" fn reset_cctx_storage_test_window_init(context: *mut c_void) {
let context = unsafe { reset_cctx_storage_test_context(context) };
context.events.push(ResetCCtxStorageTestEvent::WindowInit);
}
unsafe extern "C" fn reset_cctx_storage_test_reset_external_sequences(context: *mut c_void) {
let context = unsafe { reset_cctx_storage_test_context(context) };
context
.events
.push(ResetCCtxStorageTestEvent::ResetExternalSequences);
}
fn reset_cctx_storage_test_state(
context: &mut ResetCCtxStorageTestContext,
ldm_enable: c_int,
has_ext_seq_prod: c_int,
block_size: usize,
max_nb_seq: usize,
max_nb_ldm_seq: usize,
max_nb_external_seq: usize,
buff_in_size: usize,
buff_out_size: usize,
) -> ZSTD_rust_resetCCtxStorageState {
ZSTD_rust_resetCCtxStorageState {
callbackContext: (context as *mut ResetCCtxStorageTestContext).cast(),
ldmEnable: ldm_enable,
hasExtSeqProd: has_ext_seq_prod,
hashLog: 4,
bucketSizeLog: 2,
blockSize: block_size,
maxNbSeq: max_nb_seq,
maxNbLdmSeq: max_nb_ldm_seq,
maxNbExternalSeq: max_nb_external_seq,
buffInSize: buff_in_size,
buffOutSize: buff_out_size,
seqDefSize: size_of::<SeqDef>(),
ldmEntrySize: 8,
rawSeqSize: 12,
externalSequenceSize: size_of::<ZSTD_Sequence>(),
byteSize: 1,
wildcopyOverlength: 8,
bufferedPolicy: ZSTD_BM_BUFFERED,
setPointer: Some(reset_cctx_storage_test_set_pointer),
setSize: Some(reset_cctx_storage_test_set_size),
setInt: Some(reset_cctx_storage_test_set_int),
reserve: Some(reset_cctx_storage_test_reserve),
reserveFailed: Some(reset_cctx_storage_test_reserve_failed),
zero: Some(reset_cctx_storage_test_zero),
windowInit: Some(reset_cctx_storage_test_window_init),
resetExternalSequences: Some(reset_cctx_storage_test_reset_external_sequences),
}
}
#[test]
fn cctx_storage_preserves_ordinary_reservation_and_publication_order() {
let mut context = ResetCCtxStorageTestContext::default();
let state = reset_cctx_storage_test_state(
&mut context,
ZSTD_RUST_PS_DISABLE,
0,
128,
4,
0,
0,
0,
0,
);
assert_eq!(unsafe { ZSTD_rust_resetCCtxStorage(&state) }, 0);
assert_eq!(
context.events,
[
ResetCCtxStorageTestEvent::Reserve(
RESET_CCTX_RESERVE_ALIGNED64,
4 * size_of::<SeqDef>()
),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_SEQ_START),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 136),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LITERALS),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_MAX_NB_LIT, 128),
ResetCCtxStorageTestEvent::Int(RESET_CCTX_INT_BUFFERED_POLICY, ZSTD_BM_BUFFERED),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 0),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_INPUT_BUFFER),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_INPUT_BUFFER, 0),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 0),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_OUTPUT_BUFFER),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_OUTPUT_BUFFER, 0),
ResetCCtxStorageTestEvent::ResetExternalSequences,
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_MAX_NB_SEQ, 4),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LL_CODE),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_ML_CODE),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_OF_CODE),
ResetCCtxStorageTestEvent::Int(RESET_CCTX_INT_INITIALIZED, 1),
]
);
}
#[test]
fn cctx_storage_preserves_ldm_and_external_sequence_order() {
let mut context = ResetCCtxStorageTestContext::default();
let state = reset_cctx_storage_test_state(
&mut context,
ZSTD_RUST_PS_ENABLE,
1,
128,
4,
2,
3,
17,
19,
);
let external_size = 3 * size_of::<ZSTD_Sequence>();
assert_eq!(unsafe { ZSTD_rust_resetCCtxStorage(&state) }, 0);
assert_eq!(
context.events,
[
ResetCCtxStorageTestEvent::Reserve(
RESET_CCTX_RESERVE_ALIGNED64,
4 * size_of::<SeqDef>()
),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_SEQ_START),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_ALIGNED64, 16 * 8),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LDM_HASH),
ResetCCtxStorageTestEvent::Zero(16 * 8),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_ALIGNED64, 2 * 12),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LDM_SEQUENCES),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_MAX_NB_LDM_SEQ, 2),
ResetCCtxStorageTestEvent::WindowInit,
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_ALIGNED64, external_size),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_EXTERNAL_SEQUENCES),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_EXTERNAL_SEQ_CAPACITY, 3),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 136),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LITERALS),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_MAX_NB_LIT, 128),
ResetCCtxStorageTestEvent::Int(RESET_CCTX_INT_BUFFERED_POLICY, ZSTD_BM_BUFFERED),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 17),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_INPUT_BUFFER),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_INPUT_BUFFER, 17),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 19),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_OUTPUT_BUFFER),
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_OUTPUT_BUFFER, 19),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LDM_BUCKETS),
ResetCCtxStorageTestEvent::Zero(4),
ResetCCtxStorageTestEvent::ResetExternalSequences,
ResetCCtxStorageTestEvent::Size(RESET_CCTX_SIZE_MAX_NB_SEQ, 4),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_LL_CODE),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_ML_CODE),
ResetCCtxStorageTestEvent::Reserve(RESET_CCTX_RESERVE_BUFFER, 4),
ResetCCtxStorageTestEvent::Pointer(RESET_CCTX_POINTER_OF_CODE),
ResetCCtxStorageTestEvent::Int(RESET_CCTX_INT_INITIALIZED, 1),
]
);
}
#[test]
fn cctx_storage_propagates_reservation_failure_before_publication() {
let mut context = ResetCCtxStorageTestContext {
reserve_failure: true,
..ResetCCtxStorageTestContext::default()
};
let state = reset_cctx_storage_test_state(
&mut context,
ZSTD_RUST_PS_DISABLE,
0,
128,
4,
0,
0,
0,
0,
);
assert_eq!(
unsafe { ZSTD_rust_resetCCtxStorage(&state) },
ERROR(ZstdErrorCode::MemoryAllocation)
);
assert_eq!(
context.events,
[ResetCCtxStorageTestEvent::Reserve(
RESET_CCTX_RESERVE_ALIGNED64,
4 * size_of::<SeqDef>()
)]
);
}
#[test]
fn estimate_cctx_workspace_size_keeps_static_and_buffer_components_separate() {
let sizing = cctx_workspace_test_sizing();