feat(compress): move matchfinder policy to Rust

Move row matchfinder, block-splitter, LDM, chain-table, external-repcode, and tagged-dictionary policy leaves into Rust while preserving the existing C helper names and private parameter flow. Add boundary coverage for each policy decision.

Test Plan: cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression; cargo clippy --manifest-path rust/Cargo.toml; cargo clippy --manifest-path rust/Cargo.toml --benches; cargo clippy --manifest-path rust/Cargo.toml --tests; make -B -C lib -j2 lib; make -B -C tests -j2 test-cli-tests; make -B -C tests -j2 test-zstream
This commit is contained in:
2026-07-18 03:55:30 +02:00
parent 309e227731
commit 8ac9855309
2 changed files with 298 additions and 22 deletions
+274
View File
@@ -319,6 +319,18 @@ fn row_match_finder_used(strategy: c_int, mode: c_int) -> bool {
strategy_supports_row_match_finder(strategy) && mode == ZSTD_RUST_PS_ENABLE
}
/// C ABI for `ZSTD_rowMatchFinderSupported()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_rowMatchFinderSupported(strategy: c_int) -> c_int {
c_int::from(strategy_supports_row_match_finder(strategy))
}
/// C ABI for `ZSTD_rowMatchFinderUsed()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_rowMatchFinderUsed(strategy: c_int, mode: c_int) -> c_int {
c_int::from(row_match_finder_used(strategy, mode))
}
#[inline]
fn resolve_row_match_finder(mode: c_int, cparams: ZSTD_compressionParameters) -> c_int {
if mode != ZSTD_RUST_PS_AUTO {
@@ -331,6 +343,91 @@ fn resolve_row_match_finder(mode: c_int, cparams: ZSTD_compressionParameters) ->
}
}
/// C ABI for `ZSTD_resolveRowMatchFinderMode()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_resolveRowMatchFinderMode(
mode: c_int,
cparams: ZSTD_compressionParameters,
) -> c_int {
resolve_row_match_finder(mode, cparams)
}
#[inline]
fn resolve_block_splitter(mode: c_int, cparams: ZSTD_compressionParameters) -> c_int {
if mode != ZSTD_RUST_PS_AUTO {
return mode;
}
if cparams.strategy >= ZSTD_BTOPT && cparams.windowLog >= 17 {
ZSTD_RUST_PS_ENABLE
} else {
ZSTD_RUST_PS_DISABLE
}
}
/// C ABI for `ZSTD_resolveBlockSplitterMode()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_resolveBlockSplitterMode(
mode: c_int,
cparams: ZSTD_compressionParameters,
) -> c_int {
resolve_block_splitter(mode, cparams)
}
#[inline]
fn resolve_enable_ldm(mode: c_int, cparams: ZSTD_compressionParameters) -> c_int {
if mode != ZSTD_RUST_PS_AUTO {
return mode;
}
if cparams.strategy >= ZSTD_BTOPT && cparams.windowLog >= 27 {
ZSTD_RUST_PS_ENABLE
} else {
ZSTD_RUST_PS_DISABLE
}
}
/// C ABI for `ZSTD_resolveEnableLdm()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_resolveEnableLdm(
mode: c_int,
cparams: ZSTD_compressionParameters,
) -> c_int {
resolve_enable_ldm(mode, cparams)
}
#[inline]
fn resolve_external_repcode_search(mode: c_int, compression_level: c_int) -> c_int {
if mode != ZSTD_RUST_PS_AUTO {
return mode;
}
if compression_level < 10 {
ZSTD_RUST_PS_DISABLE
} else {
ZSTD_RUST_PS_ENABLE
}
}
/// C ABI for `ZSTD_resolveExternalRepcodeSearch()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_resolveExternalRepcodeSearch(
mode: c_int,
compression_level: c_int,
) -> c_int {
resolve_external_repcode_search(mode, compression_level)
}
#[inline]
fn cdict_indices_are_tagged(cparams: ZSTD_compressionParameters) -> bool {
cparams.strategy == ZSTD_FAST || cparams.strategy == ZSTD_DFAST
}
/// C ABI for `ZSTD_CDictIndicesAreTagged()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_cdictIndicesAreTagged(
cparams: ZSTD_compressionParameters,
) -> c_int {
c_int::from(cdict_indices_are_tagged(cparams))
}
#[inline]
fn dict_and_window_log(window_log: u32, src_size: u64, dict_size: u64) -> u32 {
/* 1ULL << ZSTD_WINDOWLOG_MAX, which is smaller for 32-bit builds. */
@@ -661,6 +758,16 @@ fn allocate_chain_table(strategy: c_int, use_row_match_finder: c_int, for_dds_di
|| (strategy != ZSTD_FAST && !row_match_finder_used(strategy, use_row_match_finder))
}
/// C ABI for `ZSTD_allocateChainTable()`.
#[no_mangle]
pub extern "C" fn ZSTD_rust_params_allocateChainTable(
strategy: c_int,
mode: c_int,
for_dds_dict: c_int,
) -> c_int {
c_int::from(allocate_chain_table(strategy, mode, for_dds_dict != 0))
}
fn estimate_match_state_size(
cparams: ZSTD_compressionParameters,
use_row_match_finder: c_int,
@@ -890,6 +997,173 @@ mod tests {
);
}
fn policy_cparams(strategy: c_int, window_log: u32) -> ZSTD_compressionParameters {
ZSTD_compressionParameters {
windowLog: window_log,
strategy,
..ZSTD_compressionParameters::default()
}
}
#[test]
fn row_match_finder_policy_preserves_strategy_and_window_boundaries() {
assert_eq!(ZSTD_rust_params_rowMatchFinderSupported(ZSTD_FAST), 0);
assert_eq!(ZSTD_rust_params_rowMatchFinderSupported(ZSTD_GREEDY), 1);
assert_eq!(ZSTD_rust_params_rowMatchFinderSupported(ZSTD_LAZY2), 1);
assert_eq!(ZSTD_rust_params_rowMatchFinderSupported(ZSTD_BTLAZY2), 0);
assert_eq!(
ZSTD_rust_params_rowMatchFinderUsed(ZSTD_GREEDY, ZSTD_RUST_PS_ENABLE),
1
);
assert_eq!(
ZSTD_rust_params_rowMatchFinderUsed(ZSTD_GREEDY, ZSTD_RUST_PS_DISABLE),
0
);
assert_eq!(
ZSTD_rust_params_rowMatchFinderUsed(ZSTD_FAST, ZSTD_RUST_PS_ENABLE),
0
);
assert_eq!(
ZSTD_rust_params_resolveRowMatchFinderMode(
ZSTD_RUST_PS_AUTO,
policy_cparams(ZSTD_GREEDY, 14),
),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveRowMatchFinderMode(
ZSTD_RUST_PS_AUTO,
policy_cparams(ZSTD_GREEDY, 15),
),
ZSTD_RUST_PS_ENABLE
);
assert_eq!(
ZSTD_rust_params_resolveRowMatchFinderMode(
ZSTD_RUST_PS_AUTO,
policy_cparams(ZSTD_BTLAZY2, 31),
),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveRowMatchFinderMode(
ZSTD_RUST_PS_ENABLE,
policy_cparams(ZSTD_FAST, 14),
),
ZSTD_RUST_PS_ENABLE
);
}
#[test]
fn block_splitter_and_ldm_policy_match_window_boundaries() {
assert_eq!(
ZSTD_rust_params_resolveBlockSplitterMode(
ZSTD_RUST_PS_AUTO,
policy_cparams(ZSTD_BTOPT, 16),
),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveBlockSplitterMode(
ZSTD_RUST_PS_AUTO,
policy_cparams(ZSTD_BTOPT, 17),
),
ZSTD_RUST_PS_ENABLE
);
assert_eq!(
ZSTD_rust_params_resolveBlockSplitterMode(
ZSTD_RUST_PS_AUTO,
policy_cparams(ZSTD_BTLAZY2, 31),
),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveBlockSplitterMode(
ZSTD_RUST_PS_ENABLE,
policy_cparams(ZSTD_FAST, 1),
),
ZSTD_RUST_PS_ENABLE
);
assert_eq!(
ZSTD_rust_params_resolveEnableLdm(ZSTD_RUST_PS_AUTO, policy_cparams(ZSTD_BTOPT, 26),),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveEnableLdm(ZSTD_RUST_PS_AUTO, policy_cparams(ZSTD_BTOPT, 27),),
ZSTD_RUST_PS_ENABLE
);
assert_eq!(
ZSTD_rust_params_resolveEnableLdm(ZSTD_RUST_PS_AUTO, policy_cparams(ZSTD_BTLAZY2, 31),),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveEnableLdm(
ZSTD_RUST_PS_DISABLE,
policy_cparams(ZSTD_BTULTRA2, 31),
),
ZSTD_RUST_PS_DISABLE
);
}
#[test]
fn chain_table_policy_matches_dds_and_row_match_finder_modes() {
assert_eq!(
ZSTD_rust_params_allocateChainTable(ZSTD_FAST, ZSTD_RUST_PS_DISABLE, 0),
0
);
assert_eq!(
ZSTD_rust_params_allocateChainTable(ZSTD_DFAST, ZSTD_RUST_PS_DISABLE, 0),
1
);
assert_eq!(
ZSTD_rust_params_allocateChainTable(ZSTD_GREEDY, ZSTD_RUST_PS_ENABLE, 0),
0
);
assert_eq!(
ZSTD_rust_params_allocateChainTable(ZSTD_FAST, ZSTD_RUST_PS_DISABLE, 1),
1
);
}
#[test]
fn external_repcode_and_cdict_tagging_match_boundaries() {
assert_eq!(
ZSTD_rust_params_resolveExternalRepcodeSearch(ZSTD_RUST_PS_AUTO, 9),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveExternalRepcodeSearch(ZSTD_RUST_PS_AUTO, 10),
ZSTD_RUST_PS_ENABLE
);
assert_eq!(
ZSTD_rust_params_resolveExternalRepcodeSearch(ZSTD_RUST_PS_DISABLE, 100),
ZSTD_RUST_PS_DISABLE
);
assert_eq!(
ZSTD_rust_params_resolveExternalRepcodeSearch(ZSTD_RUST_PS_ENABLE, -100),
ZSTD_RUST_PS_ENABLE
);
assert_eq!(
ZSTD_rust_params_cdictIndicesAreTagged(policy_cparams(ZSTD_FAST, 1)),
1
);
assert_eq!(
ZSTD_rust_params_cdictIndicesAreTagged(policy_cparams(ZSTD_DFAST, 1)),
1
);
assert_eq!(
ZSTD_rust_params_cdictIndicesAreTagged(policy_cparams(ZSTD_GREEDY, 1)),
0
);
assert_eq!(
ZSTD_rust_params_cdictIndicesAreTagged(policy_cparams(ZSTD_BTULTRA2, 1)),
0
);
}
#[test]
fn level_tables_match_representative_clevels_entries() {
let large = select_cparams(3, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_RUST_CPM_UNKNOWN);