feat(compress): move block-state confirmation to Rust

Keep C ownership of the block-state structure while delegating the confirmed-block pointer swap through a narrow two-pointer ABI leaf. Preserve every existing confirmation call site and add direct pointer-swap coverage.

Test Plan:

- cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression

- cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression --all-targets

- cargo +nightly fmt --manifest-path rust/Cargo.toml

- make -B -C lib -j2 lib

- tests/fuzzer -s4560 -t47 -i48 -v

- make -C tests -j2 test-zstream
This commit is contained in:
2026-07-18 08:23:28 +02:00
parent b44b480f17
commit 56ae331f09
2 changed files with 34 additions and 3 deletions
+5 -3
View File
@@ -269,6 +269,9 @@ size_t ZSTD_rust_copyBlockSequences(
SeqCollector* seqCollector, const SeqStore_t* seqStore,
const U32 prevRepcodes[ZSTD_REP_NUM]);
void ZSTD_rust_resetCompressedBlockState(ZSTD_compressedBlockState_t* bs);
void ZSTD_rust_confirmRepcodesAndEntropyTables(
ZSTD_compressedBlockState_t** prevCBlock,
ZSTD_compressedBlockState_t** nextCBlock);
void ZSTD_rust_storeLastLiterals(SeqStore_t* seqStorePtr,
const BYTE* anchor, size_t lastLLSize);
void ZSTD_rust_resetSeqStore(SeqStore_t* ssPtr);
@@ -2596,9 +2599,8 @@ static int ZSTD_maybeRLE(SeqStore_t const* seqStore)
static void
ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)
{
ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock;
bs->prevCBlock = bs->nextCBlock;
bs->nextCBlock = tmp;
ZSTD_rust_confirmRepcodesAndEntropyTables(
&bs->prevCBlock, &bs->nextCBlock);
}
/* Writes the block header */
+29
View File
@@ -1095,6 +1095,18 @@ pub unsafe extern "C" fn ZSTD_rust_resetCompressedBlockState(
block_state.entropy.fse.litlength_repeatMode = FSE_REPEAT_NONE;
}
/// Swaps the two C-owned block-state pointers after a block is confirmed.
///
/// The enclosing `ZSTD_blockState_t` contains C-only match-state storage, so
/// the ABI deliberately passes only the two pointer fields separately.
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_confirmRepcodesAndEntropyTables(
prev_c_block: *mut *mut ZSTD_compressedBlockState_t,
next_c_block: *mut *mut ZSTD_compressedBlockState_t,
) {
unsafe { ptr::swap(prev_c_block, next_c_block) };
}
/// Appends the final literals of a block to its sequence store.
///
/// The source and destination ranges must be valid and non-overlapping, as
@@ -3258,6 +3270,23 @@ mod tests {
);
}
#[test]
fn confirm_repcodes_and_entropy_tables_swaps_block_state_pointers() {
let mut previous_storage = std::mem::MaybeUninit::<ZSTD_compressedBlockState_t>::uninit();
let mut next_storage = std::mem::MaybeUninit::<ZSTD_compressedBlockState_t>::uninit();
let previous = previous_storage.as_mut_ptr();
let next = next_storage.as_mut_ptr();
let mut previous_ptr = previous;
let mut next_ptr = next;
unsafe {
ZSTD_rust_confirmRepcodesAndEntropyTables(&mut previous_ptr, &mut next_ptr);
}
assert_eq!(previous_ptr, next);
assert_eq!(next_ptr, previous);
}
#[test]
fn store_last_literals_copies_bytes_and_advances_only_the_literal_cursor() {
let mut sequences = [SeqDef::default(); 2];