feat(compress): move sequence copier selection to Rust
ZSTD_selectSequenceCopier combined block-delimiter validation with its private C function-pointer dispatch. Move only the scalar mode policy behind a Rust ABI shim, retaining the function-pointer switch and both sequence transfer implementations in C. Rust preserves the 0..=1 debug validation and the release fallback to no-block-delimiters for unsupported values. Test Plan: - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression` — 281 passed. - Required clippy checks for the library, benches, and tests passed before and after `cargo +nightly fmt`. - `make -B -C lib -j2 lib` and `make -B -C tests test-rust-lib-smoke` — passed. - `tests/fuzzer -s4560 -t47 -i48 -v` and `tests/fuzzer -s4560 -t56 -i57 -v` — passed. - `make -C tests -j2 test-zstream` — 84 named, 7,298 standard randomized, and 9,379 new-API randomized cases passed. - `git diff --check` and `git diff --cached --check` — passed.
This commit is contained in:
@@ -356,6 +356,7 @@ size_t ZSTD_rust_blockSizeExplicitDelimiter(const ZSTD_Sequence* inSeqs,
|
|||||||
size_t ZSTD_rust_determineBlockSize(int mode, size_t blockSize, size_t remaining,
|
size_t ZSTD_rust_determineBlockSize(int mode, size_t blockSize, size_t remaining,
|
||||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||||
U32 seqIdx);
|
U32 seqIdx);
|
||||||
|
int ZSTD_rust_selectSequenceCopier(int mode);
|
||||||
size_t ZSTD_rust_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
size_t ZSTD_rust_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
||||||
const void* dict, size_t dictSize);
|
const void* dict, size_t dictSize);
|
||||||
size_t ZSTD_rust_transferSequencesWBlockDelim(
|
size_t ZSTD_rust_transferSequencesWBlockDelim(
|
||||||
@@ -5164,12 +5165,13 @@ typedef size_t (*ZSTD_SequenceCopier_f)(ZSTD_CCtx* cctx,
|
|||||||
|
|
||||||
static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode)
|
static ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode)
|
||||||
{
|
{
|
||||||
assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode));
|
switch (ZSTD_rust_selectSequenceCopier((int)mode)) {
|
||||||
if (mode == ZSTD_sf_explicitBlockDelimiters) {
|
case ZSTD_sf_explicitBlockDelimiters:
|
||||||
return ZSTD_transferSequences_wBlockDelim;
|
return ZSTD_transferSequences_wBlockDelim;
|
||||||
}
|
case ZSTD_sf_noBlockDelimiters:
|
||||||
assert(mode == ZSTD_sf_noBlockDelimiters);
|
default:
|
||||||
return ZSTD_transferSequences_noDelim;
|
return ZSTD_transferSequences_noDelim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t determine_blockSize(ZSTD_SequenceFormat_e mode,
|
static size_t determine_blockSize(ZSTD_SequenceFormat_e mode,
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ const ZSTD_REP_NUM: usize = 3;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
const ZSTD_BM_BUFFERED: c_int = 0;
|
const ZSTD_BM_BUFFERED: c_int = 0;
|
||||||
const ZSTD_BM_STABLE: c_int = 1;
|
const ZSTD_BM_STABLE: c_int = 1;
|
||||||
|
const ZSTD_SF_NO_BLOCK_DELIMITERS: c_int = 0;
|
||||||
|
const ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS: c_int = 1;
|
||||||
const ZSTD_BLOCKSIZE_MAX: usize = 1 << 17;
|
const ZSTD_BLOCKSIZE_MAX: usize = 1 << 17;
|
||||||
const ZSTD_CONTENTSIZE_UNKNOWN: u64 = u64::MAX;
|
const ZSTD_CONTENTSIZE_UNKNOWN: u64 = u64::MAX;
|
||||||
const ZSTD_TARGET_CBLOCK_BSS_COMPRESS: c_int = 0;
|
const ZSTD_TARGET_CBLOCK_BSS_COMPRESS: c_int = 0;
|
||||||
@@ -196,6 +198,27 @@ pub extern "C" fn ZSTD_rust_inBufferForEndFlush(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select_sequence_copier(mode: c_int) -> c_int {
|
||||||
|
debug_assert!(
|
||||||
|
(ZSTD_SF_NO_BLOCK_DELIMITERS..=ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS).contains(&mode)
|
||||||
|
);
|
||||||
|
if mode == ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS {
|
||||||
|
ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS
|
||||||
|
} else {
|
||||||
|
debug_assert_eq!(mode, ZSTD_SF_NO_BLOCK_DELIMITERS);
|
||||||
|
ZSTD_SF_NO_BLOCK_DELIMITERS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Select the C-side sequence transfer policy without crossing private
|
||||||
|
/// function pointers through the Rust ABI. Invalid values retain the C
|
||||||
|
/// release fallback to the no-delimiter policy after debug validation.
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn ZSTD_rust_selectSequenceCopier(mode: c_int) -> c_int {
|
||||||
|
select_sequence_copier(mode)
|
||||||
|
}
|
||||||
|
|
||||||
/* HUF_WORKSPACE_SIZE + (MaxSeq + 2) * sizeof(unsigned), rounded up. The
|
/* HUF_WORKSPACE_SIZE + (MaxSeq + 2) * sizeof(unsigned), rounded up. The
|
||||||
* superblock leaf also accepts the larger pre-split workspace, so a fixed
|
* superblock leaf also accepts the larger pre-split workspace, so a fixed
|
||||||
* 16 KiB buffer is sufficient for this first non-splitting path on both
|
* 16 KiB buffer is sufficient for this first non-splitting path on both
|
||||||
@@ -1197,6 +1220,57 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sequence_copier_selector_returns_no_delimiters_mode() {
|
||||||
|
assert_eq!(
|
||||||
|
select_sequence_copier(ZSTD_SF_NO_BLOCK_DELIMITERS),
|
||||||
|
ZSTD_SF_NO_BLOCK_DELIMITERS
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ZSTD_rust_selectSequenceCopier(ZSTD_SF_NO_BLOCK_DELIMITERS),
|
||||||
|
ZSTD_SF_NO_BLOCK_DELIMITERS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sequence_copier_selector_returns_explicit_delimiters_mode() {
|
||||||
|
assert_eq!(
|
||||||
|
select_sequence_copier(ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS),
|
||||||
|
ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ZSTD_rust_selectSequenceCopier(ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS),
|
||||||
|
ZSTD_SF_EXPLICIT_BLOCK_DELIMITERS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn sequence_copier_selector_rejects_invalid_mode_in_debug() {
|
||||||
|
let _ = select_sequence_copier(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn sequence_copier_selector_rejects_unsupported_mode_in_debug() {
|
||||||
|
let _ = select_sequence_copier(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
#[test]
|
||||||
|
fn sequence_copier_selector_falls_back_to_no_delimiters_in_release() {
|
||||||
|
assert_eq!(
|
||||||
|
ZSTD_rust_selectSequenceCopier(-1),
|
||||||
|
ZSTD_SF_NO_BLOCK_DELIMITERS
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ZSTD_rust_selectSequenceCopier(2),
|
||||||
|
ZSTD_SF_NO_BLOCK_DELIMITERS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn invalidate_rep_codes_clears_all_entries() {
|
fn invalidate_rep_codes_clears_all_entries() {
|
||||||
let mut rep = [11u32, 22, 33];
|
let mut rep = [11u32, 22, 33];
|
||||||
|
|||||||
Reference in New Issue
Block a user