feat(compress): move MT input size hint arithmetic to Rust

ZSTDMT_nextInputSizeHint only derives a size_t hint from targetSectionSize
and inBuff.filled. Keep the MT context, public/internal entry point, and
stream orchestration in C, but delegate those two scalars to Rust. The Rust
helper uses wrapping subtraction and preserves the zero-result fallback,
including C's wrapped behavior for invalid overfill.

Test Plan:
- The three compression clippy modes passed before and after
  `cargo +nightly fmt --manifest-path rust/Cargo.toml`.
- Focused Rust tests passed: 5 `mt_next_input_size_hint` tests.
- `make -B -C lib -j2 lib` passed.
- `make -C tests test-rust-lib-smoke` passed.
- `tests/fuzzer -s4560 -t56 -i57 -v` passed: 57 tests completed.
- `make -C tests -j2 test-zstream` passed: 84 named, 6,659, and 8,055
  randomized tests completed.
- `git diff --check` and `git diff --cached --check` passed.
This commit is contained in:
2026-07-18 11:19:43 +02:00
parent effef1b8b1
commit 564c82e70f
2 changed files with 50 additions and 3 deletions
+4 -3
View File
@@ -149,6 +149,8 @@ void ZSTDMT_rust_findSynchronizationPoint(const void* inputSrc, size_t inputSize
const void* inBuffStart, size_t inBuffFilled,
int rsyncable, U64 primePower, U64 hitMask,
size_t* toLoad, int* flush);
size_t ZSTDMT_rust_nextInputSizeHint(size_t targetSectionSize,
size_t inBuffFilled);
typedef struct ZSTDMT_bufferPool_s {
ZSTDMT_RustBufferPool* rustPool;
@@ -1665,9 +1667,8 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx)
{
size_t hintInSize = mtctx->targetSectionSize - mtctx->inBuff.filled;
if (hintInSize==0) hintInSize = mtctx->targetSectionSize;
return hintInSize;
return ZSTDMT_rust_nextInputSizeHint(mtctx->targetSectionSize,
mtctx->inBuff.filled);
}
/** ZSTDMT_compressStream_generic() :
+46
View File
@@ -303,6 +303,25 @@ pub extern "C" fn ZSTD_rust_nextInputSizeHint(
)
}
#[inline]
fn mt_next_input_size_hint(target_section_size: usize, in_buff_filled: usize) -> usize {
let hint_in_size = target_section_size.wrapping_sub(in_buff_filled);
if hint_in_size == 0 {
target_section_size
} else {
hint_in_size
}
}
/// Return the next input size required by the C multithreaded streaming state.
#[no_mangle]
pub extern "C" fn ZSTDMT_rust_nextInputSizeHint(
target_section_size: usize,
in_buff_filled: usize,
) -> usize {
mt_next_input_size_hint(target_section_size, in_buff_filled)
}
#[inline]
fn bitmix(mut val: u64, len: u64) -> u64 {
val ^= val.rotate_right(49) ^ val.rotate_right(24);
@@ -1191,6 +1210,33 @@ mod tests {
);
}
#[test]
fn mt_next_input_size_hint_handles_empty_input_buffer() {
assert_eq!(mt_next_input_size_hint(128, 0), 128);
assert_eq!(ZSTDMT_rust_nextInputSizeHint(128, 0), 128);
}
#[test]
fn mt_next_input_size_hint_returns_remaining_capacity() {
assert_eq!(mt_next_input_size_hint(128, 37), 91);
assert_eq!(ZSTDMT_rust_nextInputSizeHint(128, 37), 91);
}
#[test]
fn mt_next_input_size_hint_replaces_full_buffer_with_target_size() {
assert_eq!(ZSTDMT_rust_nextInputSizeHint(128, 128), 128);
}
#[test]
fn mt_next_input_size_hint_preserves_zero_target_behavior() {
assert_eq!(ZSTDMT_rust_nextInputSizeHint(0, 0), 0);
}
#[test]
fn mt_next_input_size_hint_preserves_wrapped_overfill() {
assert_eq!(ZSTDMT_rust_nextInputSizeHint(3, 4), usize::MAX);
}
#[test]
fn in_buffer_for_end_flush_returns_stable_expected_buffer() {
let expected_src = b"input".as_ptr().cast::<c_void>();