feat(compress): move workspace size aggregation to Rust

Keep all context-sensitive workspace sizing in C, including intermediate
allocation calculations, match-state and LDM sizing, error propagation, and
diagnostics. Move only the final nine-component neededSpace aggregation
behind a scalar Rust ABI helper so its size_t wrapping behavior is explicit
and independently tested.

Test Plan:
- `cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression` -- passed before and after formatting.
- The same command with `--benches` and `--tests` -- passed before and after formatting.
- `cargo +nightly fmt --manifest-path rust/Cargo.toml` -- passed.
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression zstd_compress` -- 186 passed.
- `make -B -C lib -j2 lib` -- passed.
- `make -C tests test-rust-lib-smoke` -- passed.
- `tests/fuzzer -s4560 -t56 -i57 -v` -- passed.
- `make -C tests -j2 test-zstream` -- 84 named tests and 6,536 plus 7,961 randomized cases passed; the existing unterminated-string warning remains.
- `git diff --cached --check` -- passed.
This commit is contained in:
2026-07-18 11:49:47 +02:00
parent 0000c6d068
commit 6d4917e187
2 changed files with 99 additions and 10 deletions
+87
View File
@@ -455,6 +455,55 @@ pub extern "C" fn ZSTD_rust_sizeofCCtx(
sizeof_cctx(object_size, workspace_size, local_dict_size, mtctx_size)
}
#[inline]
fn estimate_workspace_size(
cctx_space: usize,
tmp_work_space: usize,
block_state_space: usize,
ldm_space: usize,
ldm_seq_space: usize,
match_state_size: usize,
token_space: usize,
buffer_space: usize,
external_seq_space: usize,
) -> usize {
cctx_space
.wrapping_add(tmp_work_space)
.wrapping_add(block_state_space)
.wrapping_add(ldm_space)
.wrapping_add(ldm_seq_space)
.wrapping_add(match_state_size)
.wrapping_add(token_space)
.wrapping_add(buffer_space)
.wrapping_add(external_seq_space)
}
/// Aggregate workspace-size components with C `size_t` wrapping semantics.
#[no_mangle]
pub extern "C" fn ZSTD_rust_estimateWorkspaceSize(
cctx_space: usize,
tmp_work_space: usize,
block_state_space: usize,
ldm_space: usize,
ldm_seq_space: usize,
match_state_size: usize,
token_space: usize,
buffer_space: usize,
external_seq_space: usize,
) -> usize {
estimate_workspace_size(
cctx_space,
tmp_work_space,
block_state_space,
ldm_space,
ldm_seq_space,
match_state_size,
token_space,
buffer_space,
external_seq_space,
)
}
#[inline]
fn reduce_table_internal(table: &mut [u32], reducer_value: u32, preserve_mark: bool) {
debug_assert_eq!(table.len() % ZSTD_ROWSIZE, 0);
@@ -1452,6 +1501,44 @@ mod tests {
assert_eq!(ZSTD_rust_sizeofCCtx(usize::MAX, 1, 2, 3), 5);
}
#[test]
fn estimate_workspace_size_handles_zero_components() {
assert_eq!(estimate_workspace_size(0, 0, 0, 0, 0, 0, 0, 0, 0), 0);
assert_eq!(
ZSTD_rust_estimateWorkspaceSize(0, 0, 0, 0, 0, 0, 0, 0, 0),
0
);
}
#[test]
fn estimate_workspace_size_adds_components_in_order() {
assert_eq!(estimate_workspace_size(1, 2, 3, 4, 5, 6, 7, 8, 9), 45);
assert_eq!(
ZSTD_rust_estimateWorkspaceSize(1, 2, 3, 4, 5, 6, 7, 8, 9),
45
);
}
#[test]
fn estimate_workspace_size_wraps_at_multiple_operand_positions() {
assert_eq!(
estimate_workspace_size(usize::MAX, 1, 0, 0, 0, 0, 0, 0, 0),
0
);
assert_eq!(
estimate_workspace_size(0, usize::MAX, 1, 0, 0, 0, 0, 0, 0),
0
);
assert_eq!(
estimate_workspace_size(0, 0, 0, 0, 0, usize::MAX, 1, 0, 0),
0
);
assert_eq!(
ZSTD_rust_estimateWorkspaceSize(0, 0, 0, 0, 0, 0, 0, usize::MAX, 1),
0
);
}
#[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 =