feat(compress): move window lifecycle predicates into Rust

Move shared window initialization and the empty-window and external-dictionary predicates behind the Rust compression seam. Rust now owns the projected five-field lifecycle state, while C retains the containing window and its overflow-correction counter.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1; cargo test --manifest-path rust/Cargo.toml
- ulimit -v 41943040; CARGO_BUILD_JOBS=1; cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -B -C programs -j1 zstd
- ulimit -v 41943040; make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s
This commit is contained in:
2026-07-19 19:58:18 +02:00
parent 28607551cc
commit ff57c578db
2 changed files with 80 additions and 11 deletions
+66
View File
@@ -6818,6 +6818,45 @@ const _: () = {
);
};
static WINDOW_INIT_SENTINEL: [u8; 2] = [b' ', 0];
/// Initialize the projected window fields. C retains the containing object
/// and its overflow-correction counter.
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_windowInit(state: *mut ZSTD_rust_windowUpdateState) {
if state.is_null() {
return;
}
let base = WINDOW_INIT_SENTINEL.as_ptr();
unsafe {
*state = ZSTD_rust_windowUpdateState {
nextSrc: base.wrapping_add(2).cast(),
base: base.cast(),
dictBase: base.cast(),
dictLimit: ZSTD_WINDOW_START_INDEX,
lowLimit: ZSTD_WINDOW_START_INDEX,
};
}
}
#[no_mangle]
pub extern "C" fn ZSTD_rust_windowIsEmpty(
next_src: *const c_void,
base: *const c_void,
dict_limit: u32,
low_limit: u32,
) -> c_uint {
(dict_limit == ZSTD_WINDOW_START_INDEX
&& low_limit == ZSTD_WINDOW_START_INDEX
&& (next_src as usize).wrapping_sub(base as usize) == ZSTD_WINDOW_START_INDEX as usize)
as c_uint
}
#[no_mangle]
pub extern "C" fn ZSTD_rust_windowHasExtDict(dict_limit: u32, low_limit: u32) -> c_uint {
(low_limit < dict_limit) as c_uint
}
/// Update the rolling prefix/ext-dictionary window for one input segment.
/// C owns the containing match state; Rust owns this five-field transition.
#[no_mangle]
@@ -12608,6 +12647,33 @@ mod tests {
assert_eq!(state, original);
}
#[test]
fn window_init_sets_empty_sentinel_and_dictionary_predicates() {
let mut state = ZSTD_rust_windowUpdateState {
nextSrc: ptr::null(),
base: ptr::null(),
dictBase: ptr::null(),
dictLimit: 0,
lowLimit: 0,
};
unsafe { ZSTD_rust_windowInit(&mut state) };
assert_eq!(state.dictLimit, ZSTD_WINDOW_START_INDEX);
assert_eq!(state.lowLimit, ZSTD_WINDOW_START_INDEX);
assert_eq!(state.dictBase as usize, state.base as usize);
assert_eq!(
(state.nextSrc as usize).wrapping_sub(state.base as usize),
ZSTD_WINDOW_START_INDEX as usize
);
assert_eq!(
ZSTD_rust_windowIsEmpty(state.nextSrc, state.base, state.dictLimit, state.lowLimit),
1
);
assert_eq!(ZSTD_rust_windowHasExtDict(10, 2), 1);
assert_eq!(ZSTD_rust_windowHasExtDict(10, 10), 0);
}
#[test]
fn window_update_preserves_contiguous_input_and_clips_overlapping_extdict() {
let storage = [0u8; 64];