From ccec75e1495be8f45f4c6e4adf99b28a6f30a3ab Mon Sep 17 00:00:00 2001 From: ddidderr Date: Mon, 20 Jul 2026 18:44:38 +0200 Subject: [PATCH] refactor(mt): move serial reset error policy to Rust Project the private serial-state reset result into Rust for the stream-initialization error decision while retaining C-owned allocation, serial-state mutation, dictionary setup, synchronization, callback order, and ABI layouts. Nonzero callback status preserves the existing memory_allocation error path. Test Plan: ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings; cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings; cargo test --manifest-path rust/cli/Cargo.toml --all-targets (188 passed); cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check; make -j1; ./tests/rustLibSmoke; make -j1 -C tests test (all shell tests, large streaming tests, native tester, fuzzer phases, and zstream tester passed). --- lib/compress/zstdmt_compress.c | 7 +++---- rust/src/zstdmt_compress.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 369217aaf..26f98387c 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -853,6 +853,7 @@ size_t ZSTDMT_rust_initCStream( ZSTDMT_initResetStreamFn resetStream, ZSTDMT_initDictionaryFn updateDictionary, ZSTDMT_initSerialResetFn serialReset); +size_t ZSTDMT_rust_initSerialResetResult(int status); typedef void (*ZSTDMT_resetStreamCallbackFn)(void* opaque); typedef struct { void* callbackContext; @@ -2779,12 +2780,10 @@ static size_t ZSTDMT_initCStreamUpdateDictionary(void* opaque) static size_t ZSTDMT_initCStreamSerialReset(void* opaque, size_t targetSectionSize) { ZSTDMT_initCStreamState* const state = (ZSTDMT_initCStreamState*)opaque; - if (ZSTDMT_serialState_reset( + return ZSTDMT_rust_initSerialResetResult(ZSTDMT_serialState_reset( &state->mtctx->serial, state->mtctx->seqPool, state->params, targetSectionSize, state->dict, state->dictSize, - state->dictContentType)) - return ERROR(memory_allocation); - return 0; + state->dictContentType)); } /* ====================================== */ diff --git a/rust/src/zstdmt_compress.rs b/rust/src/zstdmt_compress.rs index b72f04e93..6938aacb0 100644 --- a/rust/src/zstdmt_compress.rs +++ b/rust/src/zstdmt_compress.rs @@ -2136,6 +2136,23 @@ fn normalize_mt_job_size(job_size: usize, job_size_min: usize, job_size_max: usi } } +#[inline] +fn init_serial_reset_result(status: c_int) -> usize { + if status != 0 { + ERROR(ZstdErrorCode::MemoryAllocation) + } else { + 0 + } +} + +/// Map the private C serial-reset result to the MT stream-initialization ABI +/// error. C retains serial-state allocation and mutation; Rust owns only this +/// scalar error policy. +#[no_mangle] +pub extern "C" fn ZSTDMT_rust_initSerialResetResult(status: c_int) -> usize { + init_serial_reset_result(status) +} + #[inline] fn init_round_buffer_capacity( projection: ZSTDMT_initCStreamProjection, @@ -6590,6 +6607,18 @@ mod tests { ); } + #[test] + fn init_serial_reset_result_maps_nonzero_status_to_memory_error() { + let expected_error = ERROR(ZstdErrorCode::MemoryAllocation); + + assert_eq!(init_serial_reset_result(0), 0); + assert_eq!(ZSTDMT_rust_initSerialResetResult(0), 0); + for status in [1, -1, 2] { + assert_eq!(init_serial_reset_result(status), expected_error); + assert_eq!(ZSTDMT_rust_initSerialResetResult(status), expected_error); + } + } + #[test] fn init_c_stream_preserves_success_order_and_normalization() { let projection = init_projection();