feat(compress): move simple strategy selection into Rust
The Rust simple-compression entry points already owned the dispatch, but ZSTD_rust_compressCCtxStrategy still called the C parameter cascade to decide whether a fast Rust frame path was safe. That left a small policy leaf in the C implementation and made the dispatch boundary harder to test in isolation. Implement the helper in Rust by using the existing Rust table-selection and C-parameter-adjustment functions with the same source-size, dictionary-mode, and automatic-adjustment inputs as the C code. Leave only the C ABI declaration and add tests for the table thresholds, default-level behavior, and negative fast-level behavior. The private context reset and fallback compression paths remain unchanged. Test Plan: - `cargo test --manifest-path rust/Cargo.toml --lib zstd_compress -- --test-threads=1` -- passed (234 tests). - `cargo clippy --manifest-path rust/Cargo.toml --lib -- -D warnings` -- passed. - `cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check` -- passed. - `make -B -C lib -j2 lib` -- passed. - `make -C tests -j2 test-rust-lib-smoke` -- passed. - Full-target clippy remains blocked by pre-existing test-only `manual_repeat_n` and `manual_dangling_ptr` warnings outside this seam.
This commit is contained in:
@@ -3849,13 +3849,6 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
|
||||
|
||||
/* The Rust simple API still needs the C-owned context reset, but does not
|
||||
* cross the private context layout. */
|
||||
int ZSTD_rust_compressCCtxStrategy(size_t srcSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters const params = ZSTD_getParams_internal(
|
||||
compressionLevel, srcSize, 0, ZSTD_cpm_noAttachDict);
|
||||
return (int)params.cParams.strategy;
|
||||
}
|
||||
|
||||
size_t ZSTD_rust_resetCCtxForSimpleCompression(void* cctx)
|
||||
{
|
||||
return ZSTD_CCtx_reset((ZSTD_CCtx*)cctx, ZSTD_reset_session_and_parameters);
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::zstd_compress_frame::{
|
||||
use crate::zstd_compress_literals::min_gain;
|
||||
use crate::zstd_compress_params::{
|
||||
ZSTD_rust_params_adjustCParams, ZSTD_rust_params_maxNbSeq, ZSTD_rust_params_selectCParams,
|
||||
ZSTD_RUST_CPM_NO_ATTACH_DICT, ZSTD_RUST_PS_DISABLE,
|
||||
ZSTD_RUST_CPM_NO_ATTACH_DICT, ZSTD_RUST_PS_AUTO, ZSTD_RUST_PS_DISABLE,
|
||||
};
|
||||
use crate::zstd_compress_sequences::SeqDef;
|
||||
use crate::zstd_compress_stats::{
|
||||
@@ -44,7 +44,6 @@ unsafe extern "C" {
|
||||
src_size: usize,
|
||||
compression_level: c_int,
|
||||
) -> usize;
|
||||
fn ZSTD_rust_compressCCtxStrategy(src_size: usize, compression_level: c_int) -> c_int;
|
||||
fn ZSTD_rust_resetCCtxForSimpleCompressionSession(cctx: *mut c_void) -> usize;
|
||||
fn ZSTD_rust_markSimpleCompression2Complete(cctx: *mut c_void);
|
||||
fn ZSTD_rust_simpleCompress2Level(cctx: *const c_void, src_size: usize) -> c_int;
|
||||
@@ -142,6 +141,33 @@ fn target_c_block_size_action(
|
||||
}
|
||||
}
|
||||
|
||||
/// Select the strategy used by the simple compression entry points.
|
||||
///
|
||||
/// This is the Rust equivalent of the strategy portion of
|
||||
/// `ZSTD_getParams_internal(..., ZSTD_cpm_noAttachDict)`: use the actual
|
||||
/// source size for table selection, then apply the ordinary automatic
|
||||
/// parameter adjustment before dispatching to the Rust or C frame path.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ZSTD_rust_compressCCtxStrategy(
|
||||
src_size: usize,
|
||||
compression_level: c_int,
|
||||
) -> c_int {
|
||||
let cparams = ZSTD_rust_params_selectCParams(
|
||||
compression_level,
|
||||
src_size as u64,
|
||||
0,
|
||||
ZSTD_RUST_CPM_NO_ATTACH_DICT,
|
||||
);
|
||||
ZSTD_rust_params_adjustCParams(
|
||||
cparams,
|
||||
src_size as u64,
|
||||
0,
|
||||
ZSTD_RUST_CPM_NO_ATTACH_DICT,
|
||||
ZSTD_RUST_PS_AUTO,
|
||||
)
|
||||
.strategy
|
||||
}
|
||||
|
||||
/// Classify the target-sized block policy without crossing the C context ABI.
|
||||
///
|
||||
/// C calls this once before the superblock attempt to classify the RLE
|
||||
@@ -1205,7 +1231,7 @@ pub unsafe extern "C" fn ZSTD_compress(
|
||||
) -> usize {
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let strategy = unsafe { ZSTD_rust_compressCCtxStrategy(src_size, compression_level) };
|
||||
let strategy = ZSTD_rust_compressCCtxStrategy(src_size, compression_level);
|
||||
if strategy != ZSTD_FAST && strategy != ZSTD_DFAST {
|
||||
let cctx = unsafe { ZSTD_createCCtx() };
|
||||
if cctx.is_null() {
|
||||
@@ -1250,7 +1276,7 @@ pub unsafe extern "C" fn ZSTD_compressCCtx(
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let strategy = unsafe { ZSTD_rust_compressCCtxStrategy(src_size, compression_level) };
|
||||
let strategy = ZSTD_rust_compressCCtxStrategy(src_size, compression_level);
|
||||
if strategy != ZSTD_FAST && strategy != ZSTD_DFAST {
|
||||
return unsafe {
|
||||
ZSTD_compress_usingDict(
|
||||
@@ -1394,6 +1420,12 @@ mod tests {
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
const ZSTD_GREEDY: c_int = 3;
|
||||
const ZSTD_LAZY: c_int = 4;
|
||||
const ZSTD_BTULTRA: c_int = 8;
|
||||
const ZSTD_BTOPT: c_int = 7;
|
||||
const ZSTD_BTULTRA2: c_int = 9;
|
||||
|
||||
fn system_round_trip(compressed: &[u8]) -> Option<Vec<u8>> {
|
||||
let mut child = Command::new("zstd")
|
||||
.args(["-q", "-d", "-c"])
|
||||
@@ -1431,6 +1463,32 @@ mod tests {
|
||||
output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_strategy_follows_source_size_tiers() {
|
||||
assert_eq!(ZSTD_rust_compressCCtxStrategy(0, 1), ZSTD_FAST);
|
||||
assert_eq!(ZSTD_rust_compressCCtxStrategy(16 * 1024, 5), ZSTD_LAZY);
|
||||
assert_eq!(
|
||||
ZSTD_rust_compressCCtxStrategy(16 * 1024 + 1, 5),
|
||||
ZSTD_GREEDY
|
||||
);
|
||||
assert_eq!(ZSTD_rust_compressCCtxStrategy(128 * 1024, 16), ZSTD_BTULTRA);
|
||||
assert_eq!(ZSTD_rust_compressCCtxStrategy(256 * 1024, 16), ZSTD_BTULTRA);
|
||||
assert_eq!(
|
||||
ZSTD_rust_compressCCtxStrategy(256 * 1024 + 1, 16),
|
||||
ZSTD_BTOPT
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_strategy_preserves_default_and_fast_level_selection() {
|
||||
assert_eq!(ZSTD_rust_compressCCtxStrategy(64 * 1024, 0), ZSTD_DFAST);
|
||||
assert_eq!(ZSTD_rust_compressCCtxStrategy(1024 * 1024, -5), ZSTD_FAST);
|
||||
assert_eq!(
|
||||
ZSTD_rust_compressCCtxStrategy(1024 * 1024, 22),
|
||||
ZSTD_BTULTRA2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reduce_table_applies_threshold_and_wrapping_subtraction() {
|
||||
let mut table = [0, 1, 2, 3, 4, 5, 6, u32::MAX, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
Reference in New Issue
Block a user