feat(compress): move next input hint policy to Rust
Keep ZSTD_nextInputSizeHint's C-owned state-machine and MT routing while moving its mode-dependent arithmetic behind a narrow scalar ABI. Rust now receives the buffer mode and four size fields, preserving stable-buffer capacity, buffered target remainder, and the zero-remainder block-size fallback without exposing ZSTD_CCtx. Test Plan: - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression next_input_size_hint` -- passed (3 tests) - `make -B -C lib -j2 lib` -- passed - `make -C tests -j2 fuzzer` and `./tests/fuzzer -s4560 -t47 -i48 -v` -- passed - Required clippy, nightly fmt, and staged diff checks -- passed
This commit is contained in:
@@ -72,6 +72,9 @@ unsafe extern "C" {
|
||||
|
||||
const ZSTD_FAST: c_int = 1;
|
||||
const ZSTD_DFAST: c_int = 2;
|
||||
#[cfg(test)]
|
||||
const ZSTD_BM_BUFFERED: c_int = 0;
|
||||
const ZSTD_BM_STABLE: c_int = 1;
|
||||
const ZSTD_BLOCKSIZE_MAX: usize = 1 << 17;
|
||||
const ZSTD_CONTENTSIZE_UNKNOWN: u64 = u64::MAX;
|
||||
const ZSTD_TARGET_CBLOCK_BSS_COMPRESS: c_int = 0;
|
||||
@@ -216,6 +219,44 @@ pub unsafe extern "C" fn ZSTD_rust_updateFrameProgression(
|
||||
) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_input_size_hint(
|
||||
in_buffer_mode: c_int,
|
||||
block_size_max: usize,
|
||||
stable_in_not_consumed: usize,
|
||||
in_buff_target: usize,
|
||||
in_buff_pos: usize,
|
||||
) -> usize {
|
||||
if in_buffer_mode == ZSTD_BM_STABLE {
|
||||
return block_size_max.wrapping_sub(stable_in_not_consumed);
|
||||
}
|
||||
|
||||
let hint_in_size = in_buff_target.wrapping_sub(in_buff_pos);
|
||||
if hint_in_size == 0 {
|
||||
block_size_max
|
||||
} else {
|
||||
hint_in_size
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the next input size required by the C streaming state machine.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ZSTD_rust_nextInputSizeHint(
|
||||
in_buffer_mode: c_int,
|
||||
block_size_max: usize,
|
||||
stable_in_not_consumed: usize,
|
||||
in_buff_target: usize,
|
||||
in_buff_pos: usize,
|
||||
) -> usize {
|
||||
next_input_size_hint(
|
||||
in_buffer_mode,
|
||||
block_size_max,
|
||||
stable_in_not_consumed,
|
||||
in_buff_target,
|
||||
in_buff_pos,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bitmix(mut val: u64, len: u64) -> u64 {
|
||||
val ^= val.rotate_right(49) ^ val.rotate_right(24);
|
||||
@@ -999,6 +1040,30 @@ mod tests {
|
||||
assert_eq!(produced, 220);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn next_input_size_hint_uses_remaining_stable_block_capacity() {
|
||||
let hint = ZSTD_rust_nextInputSizeHint(ZSTD_BM_STABLE, 256, 37, 99, 12);
|
||||
|
||||
assert_eq!(next_input_size_hint(ZSTD_BM_STABLE, 256, 37, 99, 12), 219);
|
||||
assert_eq!(hint, 219);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn next_input_size_hint_replaces_empty_buffered_hint_with_block_size() {
|
||||
assert_eq!(
|
||||
ZSTD_rust_nextInputSizeHint(ZSTD_BM_BUFFERED, 256, 37, 128, 128),
|
||||
256
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn next_input_size_hint_returns_nonzero_buffered_hint() {
|
||||
assert_eq!(
|
||||
ZSTD_rust_nextInputSizeHint(ZSTD_BM_BUFFERED, 256, 37, 128, 32),
|
||||
96
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_one_shot_abi_is_c_compatible() {
|
||||
let entry: unsafe extern "C" fn(*mut c_void, usize, *const c_void, usize, c_int) -> usize =
|
||||
|
||||
Reference in New Issue
Block a user