feat(compress): move window clearing leaf into Rust

Keep the private ZSTD_window_t layout and pointer-difference calculation in C,
then route the size_t-to-U32 conversion and paired limit writes through a small
Rust ABI leaf. This removes the inline C window-clear implementation while
preserving its overflow behavior at both single-threaded and multithreaded
call sites.

Test Plan:
- cargo test --manifest-path rust/Cargo.toml --lib zstd_compress::tests (77 passed)
- make -C programs -j2 zstd
- rustfmt +nightly --edition 2021 rust/src/zstd_compress.rs --check
- make -C tests -j2 test-cli-tests (41 passed)
- make -C tests -j2 test-legacy test-invalidDictionaries test-decodecorpus test-rust-lib-smoke (passed)
- git diff --check
This commit is contained in:
2026-07-18 17:23:33 +02:00
parent 98cca9aa0f
commit c057bcbbdf
4 changed files with 54 additions and 16 deletions
+42
View File
@@ -859,6 +859,24 @@ pub unsafe extern "C" fn ZSTD_rust_invalidateRepCodes(rep: *mut u32) {
rep.fill(0);
}
/// Clear a C-owned compression window using the original `size_t`-to-`U32`
/// conversion. The caller computes the pointer difference while the private
/// `ZSTD_window_t` layout remains entirely on the C side.
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_windowClear(
end_t: usize,
low_limit: *mut u32,
dict_limit: *mut u32,
) {
debug_assert!(!low_limit.is_null());
debug_assert!(!dict_limit.is_null());
let end = end_t as u32;
unsafe {
*low_limit = end;
*dict_limit = end;
}
}
#[inline]
fn zeroed_state() -> ZSTD_compressedBlockState_t {
/* The state contains only integer arrays and enum fields. */
@@ -2146,6 +2164,30 @@ mod tests {
assert_eq!(rep, [0; ZSTD_REP_NUM]);
}
#[test]
fn window_clear_writes_the_same_end_to_both_limits() {
let mut low_limit = 11u32;
let mut dict_limit = 22u32;
unsafe { ZSTD_rust_windowClear(0x1234_5678, &mut low_limit, &mut dict_limit) };
assert_eq!(low_limit, 0x1234_5678);
assert_eq!(dict_limit, 0x1234_5678);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn window_clear_truncates_a_large_size_t_like_c_u32_cast() {
let mut low_limit = 11u32;
let mut dict_limit = 22u32;
let end_t = 0x1_0000_0000usize + 0x89ab_cdef;
unsafe { ZSTD_rust_windowClear(end_t, &mut low_limit, &mut dict_limit) };
assert_eq!(low_limit, 0x89ab_cdef);
assert_eq!(dict_limit, 0x89ab_cdef);
}
#[test]
fn sizeof_local_dict_ignores_size_without_a_buffer() {
assert_eq!(sizeof_local_dict(0, 37, 11), 11);