feat(compress): move match index reduction orchestration to Rust
ZSTD_reduceIndex previously selected and reduced each match table through separate C helpers, even though the 16-cell reduction leaf already lived in Rust. Keep C responsible for match-state access, table allocation policy, nullable table selection, btlazy2 strategy selection, and the surrounding workspace/window/dictionary state transition. Add one narrow Rust ABI that receives only the validated hash, chain, and hash3 table slices and delegates to the existing reducer, preserving chain markers only when requested and keeping threshold and U32 wrapping arithmetic unchanged. Focused tests cover zero-sized optional tables, marker routing, and threshold behavior. Test Plan: - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression zstd_compress::tests::reduce_` -- 5 passed. - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression` -- 344 passed. - `make -C lib -j2 lib-mt` and `make -C lib -j2 lib-nomt` -- passed. - `make -C tests -j2 test-zstream` -- 84 named, 6,814 standard randomized, and 8,955 new-API randomized cases passed. - Required compression clippy library/benches/tests, nightly fmt, and the repeated three clippy checks -- passed.
This commit is contained in:
@@ -708,8 +708,8 @@ fn reduce_table_internal(table: &mut [u32], reducer_value: u32, preserve_mark: b
|
||||
|
||||
/// Rust implementation of the C match-table reduction leaf.
|
||||
///
|
||||
/// The C wrappers select the ordinary or btlazy2 policy by passing a clear
|
||||
/// zero/one `preserve_mark` value; `ZSTD_reduceIndex` remains C-owned.
|
||||
/// The C caller supplies a clear zero/one `preserve_mark` value for the
|
||||
/// strategy-specific btlazy2 policy.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_reduceTable(
|
||||
table: *mut u32,
|
||||
@@ -728,6 +728,35 @@ pub unsafe extern "C" fn ZSTD_rust_reduceTable(
|
||||
reduce_table_internal(table, reducer_value, preserve_mark != 0);
|
||||
}
|
||||
|
||||
/// Reduce the match tables selected by C's stateful overflow-correction path.
|
||||
///
|
||||
/// C retains match-state access and table selection. Each non-zero size is
|
||||
/// paired with a validated mutable table pointer; zero-sized optional tables
|
||||
/// may use null pointers. Only the chain table receives the btlazy2 marker
|
||||
/// policy.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_reduceIndex(
|
||||
hash_table: *mut u32,
|
||||
hash_size: u32,
|
||||
chain_table: *mut u32,
|
||||
chain_size: u32,
|
||||
hash_table3: *mut u32,
|
||||
hash_size3: u32,
|
||||
reducer_value: u32,
|
||||
preserve_chain_mark: c_int,
|
||||
) {
|
||||
debug_assert!(!hash_table.is_null() || hash_size == 0);
|
||||
debug_assert!(!chain_table.is_null() || chain_size == 0);
|
||||
debug_assert!(!hash_table3.is_null() || hash_size3 == 0);
|
||||
debug_assert!(preserve_chain_mark == 0 || preserve_chain_mark == 1);
|
||||
|
||||
unsafe {
|
||||
ZSTD_rust_reduceTable(hash_table, hash_size, reducer_value, 0);
|
||||
ZSTD_rust_reduceTable(chain_table, chain_size, reducer_value, preserve_chain_mark);
|
||||
ZSTD_rust_reduceTable(hash_table3, hash_size3, reducer_value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies a CDict match table into a CCtx, removing short-cache tags when the
|
||||
/// C-owned compression parameters say the source table is tagged.
|
||||
#[no_mangle]
|
||||
@@ -1266,6 +1295,64 @@ mod tests {
|
||||
assert_eq!(table[ZSTD_ROWSIZE * 2 - 1], u32::MAX - 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reduce_index_accepts_zero_sized_optional_tables() {
|
||||
let mut hash_table = [0u32; ZSTD_ROWSIZE];
|
||||
hash_table[..4].copy_from_slice(&[1, 2, 5, u32::MAX]);
|
||||
|
||||
unsafe {
|
||||
ZSTD_rust_reduceIndex(
|
||||
hash_table.as_mut_ptr(),
|
||||
hash_table.len() as u32,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
);
|
||||
ZSTD_rust_reduceIndex(
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
u32::MAX,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(&hash_table[..4], &[0, 0, 2, u32::MAX - 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reduce_index_preserves_the_marker_only_in_the_chain_table() {
|
||||
let mut hash_table = [0u32; ZSTD_ROWSIZE];
|
||||
let mut chain_table = [0u32; ZSTD_ROWSIZE];
|
||||
let mut hash_table3 = [0u32; ZSTD_ROWSIZE];
|
||||
hash_table[0] = ZSTD_DUBT_UNSORTED_MARK;
|
||||
chain_table[0] = ZSTD_DUBT_UNSORTED_MARK;
|
||||
hash_table3[0] = ZSTD_DUBT_UNSORTED_MARK;
|
||||
|
||||
unsafe {
|
||||
ZSTD_rust_reduceIndex(
|
||||
hash_table.as_mut_ptr(),
|
||||
hash_table.len() as u32,
|
||||
chain_table.as_mut_ptr(),
|
||||
chain_table.len() as u32,
|
||||
hash_table3.as_mut_ptr(),
|
||||
hash_table3.len() as u32,
|
||||
3,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(hash_table[0], 0);
|
||||
assert_eq!(chain_table[0], ZSTD_DUBT_UNSORTED_MARK);
|
||||
assert_eq!(hash_table3[0], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copy_cdict_table_removes_short_cache_tags() {
|
||||
let source = [0x1234_56ff, 0xdead_beef, 0x0000_0100, u32::MAX];
|
||||
|
||||
Reference in New Issue
Block a user