feat(compress): move CCtx parameter bounds to Rust
Route public CCtx parameter bounds through the Rust policy implementation while keeping build-specific MT limits supplied by the C configuration. Preserve clamping and validation behavior for migrated parameters and add focused Rust coverage. 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:
+24
-212
@@ -81,12 +81,15 @@ size_t ZSTD_rust_params_maxNbSeq(size_t blockSize, U32 minMatch,
|
||||
size_t ZSTD_rust_params_resolveMaxBlockSize(size_t maxBlockSize);
|
||||
|
||||
/* CCtx parameter state is mirrored by rust/src/zstd_compress_params_api.rs.
|
||||
* Keep bounds and build-configuration policy in C, and expose only the
|
||||
* private helpers required by that Rust ABI implementation. */
|
||||
* Rust owns parameter bounds and clamping; C exposes only the
|
||||
* build-configuration values required by that narrow ABI. */
|
||||
ZSTD_bounds ZSTD_rust_cctx_params_get_bounds(int param);
|
||||
size_t ZSTD_rust_cctx_params_clamp_bounds(int param, int* value);
|
||||
int ZSTD_rust_cctx_params_within_bounds(int param, int value);
|
||||
int ZSTD_rust_cctx_params_is_multithreaded(void);
|
||||
int ZSTD_rust_cctx_params_nb_workers_max(void);
|
||||
int ZSTD_rust_cctx_params_job_size_min(void);
|
||||
int ZSTD_rust_cctx_params_job_size_max(void);
|
||||
ZSTD_CCtx_params* ZSTD_rust_createCCtxParams(ZSTD_customMem customMem);
|
||||
size_t ZSTD_rust_freeCCtxParams(ZSTD_CCtx_params* params);
|
||||
size_t ZSTD_rust_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams,
|
||||
@@ -600,216 +603,7 @@ static void ZSTD_CCtxParams_setZstdParams(
|
||||
|
||||
ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
||||
{
|
||||
ZSTD_bounds bounds = { 0, 0, 0 };
|
||||
|
||||
switch(param)
|
||||
{
|
||||
/* The compression level and the seven core compression parameters are
|
||||
* bounded by the Rust leaf. */
|
||||
case ZSTD_c_compressionLevel:
|
||||
case ZSTD_c_windowLog:
|
||||
case ZSTD_c_hashLog:
|
||||
case ZSTD_c_chainLog:
|
||||
case ZSTD_c_searchLog:
|
||||
case ZSTD_c_minMatch:
|
||||
case ZSTD_c_targetLength:
|
||||
case ZSTD_c_strategy:
|
||||
return ZSTD_rust_params_getBounds((int)param);
|
||||
|
||||
case ZSTD_c_contentSizeFlag:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_checksumFlag:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_dictIDFlag:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_nbWorkers:
|
||||
bounds.lowerBound = 0;
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
bounds.upperBound = ZSTDMT_NBWORKERS_MAX;
|
||||
#else
|
||||
bounds.upperBound = 0;
|
||||
#endif
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_jobSize:
|
||||
bounds.lowerBound = 0;
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
bounds.upperBound = ZSTDMT_JOBSIZE_MAX;
|
||||
#else
|
||||
bounds.upperBound = 0;
|
||||
#endif
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_overlapLog:
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;
|
||||
bounds.upperBound = ZSTD_OVERLAPLOG_MAX;
|
||||
#else
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 0;
|
||||
#endif
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_enableDedicatedDictSearch:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_enableLongDistanceMatching:
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_ldmHashLog:
|
||||
bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN;
|
||||
bounds.upperBound = ZSTD_LDM_HASHLOG_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_ldmMinMatch:
|
||||
bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN;
|
||||
bounds.upperBound = ZSTD_LDM_MINMATCH_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_ldmBucketSizeLog:
|
||||
bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;
|
||||
bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_ldmHashRateLog:
|
||||
bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN;
|
||||
bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX;
|
||||
return bounds;
|
||||
|
||||
/* experimental parameters */
|
||||
case ZSTD_c_rsyncable:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_forceMaxWindow :
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_format:
|
||||
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
||||
bounds.lowerBound = ZSTD_f_zstd1;
|
||||
bounds.upperBound = ZSTD_f_zstd1_magicless; /* note : how to ensure at compile time that this is the highest value enum ? */
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_forceAttachDict:
|
||||
ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);
|
||||
bounds.lowerBound = ZSTD_dictDefaultAttach;
|
||||
bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_literalCompressionMode:
|
||||
ZSTD_STATIC_ASSERT(ZSTD_ps_auto < ZSTD_ps_enable && ZSTD_ps_enable < ZSTD_ps_disable);
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_targetCBlockSize:
|
||||
bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
|
||||
bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_srcSizeHint:
|
||||
bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;
|
||||
bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_stableInBuffer:
|
||||
case ZSTD_c_stableOutBuffer:
|
||||
bounds.lowerBound = (int)ZSTD_bm_buffered;
|
||||
bounds.upperBound = (int)ZSTD_bm_stable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_blockDelimiters:
|
||||
bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;
|
||||
bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_validateSequences:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_splitAfterSequences:
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_blockSplitterLevel:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = ZSTD_BLOCKSPLITTER_LEVEL_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_useRowMatchFinder:
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_deterministicRefPrefix:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_prefetchCDictTables:
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_enableSeqProducerFallback:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_maxBlockSize:
|
||||
bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;
|
||||
bounds.upperBound = ZSTD_BLOCKSIZE_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_repcodeResolution:
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
default:
|
||||
bounds.error = ERROR(parameter_unsupported);
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
|
||||
/* ZSTD_cParam_clampBounds:
|
||||
* Clamps the value into the bounded range.
|
||||
*/
|
||||
static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
|
||||
{
|
||||
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
|
||||
if (ZSTD_isError(bounds.error)) return bounds.error;
|
||||
if (*value < bounds.lowerBound) *value = bounds.lowerBound;
|
||||
if (*value > bounds.upperBound) *value = bounds.upperBound;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_rust_cctx_params_clamp_bounds(int param, int* value)
|
||||
{
|
||||
return ZSTD_cParam_clampBounds((ZSTD_cParameter)param, value);
|
||||
}
|
||||
|
||||
int ZSTD_rust_cctx_params_within_bounds(int param, int value)
|
||||
{
|
||||
return ZSTD_cParam_withinBounds((ZSTD_cParameter)param, value);
|
||||
return ZSTD_rust_cctx_params_get_bounds((int)param);
|
||||
}
|
||||
|
||||
int ZSTD_rust_cctx_params_is_multithreaded(void)
|
||||
@@ -821,6 +615,15 @@ int ZSTD_rust_cctx_params_is_multithreaded(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZSTD_rust_cctx_params_nb_workers_max(void)
|
||||
{
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
return ZSTDMT_NBWORKERS_MAX;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZSTD_rust_cctx_params_job_size_min(void)
|
||||
{
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
@@ -830,6 +633,15 @@ int ZSTD_rust_cctx_params_job_size_min(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZSTD_rust_cctx_params_job_size_max(void)
|
||||
{
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
return ZSTDMT_JOBSIZE_MAX;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define BOUNDCHECK(cParam, val) \
|
||||
do { \
|
||||
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
|
||||
|
||||
@@ -12,12 +12,10 @@
|
||||
//! default-resolution policy.
|
||||
|
||||
use crate::errors::{ZstdErrorCode, ERROR};
|
||||
#[cfg(test)]
|
||||
use crate::zstd_compress_params::ZSTD_bounds;
|
||||
use crate::zstd_compress_params::{
|
||||
ZSTD_compressionParameters, ZSTD_frameParameters, ZSTD_parameters,
|
||||
ZSTD_rust_params_checkCParams, ZSTD_rust_params_resolveMaxBlockSize, ZSTD_RUST_PS_DISABLE,
|
||||
ZSTD_RUST_PS_ENABLE,
|
||||
ZSTD_bounds, ZSTD_compressionParameters, ZSTD_frameParameters, ZSTD_parameters,
|
||||
ZSTD_rust_params_checkCParams, ZSTD_rust_params_getBounds,
|
||||
ZSTD_rust_params_resolveMaxBlockSize, ZSTD_RUST_PS_DISABLE, ZSTD_RUST_PS_ENABLE,
|
||||
};
|
||||
use std::mem::size_of;
|
||||
use std::os::raw::{c_int, c_void};
|
||||
@@ -125,9 +123,7 @@ pub struct ZSTD_CCtx_params {
|
||||
|
||||
const DEFAULT_CLEVEL: c_int = 3;
|
||||
const NO_CLEVEL: c_int = 0;
|
||||
#[cfg(test)]
|
||||
const PS_AUTO: c_int = 0;
|
||||
#[cfg(test)]
|
||||
const PS_DISABLE: c_int = 2;
|
||||
|
||||
/* Private strategy values used by the existing C policy helpers. */
|
||||
@@ -135,9 +131,7 @@ const STRATEGY_GREEDY: c_int = 3;
|
||||
const STRATEGY_LAZY2: c_int = 5;
|
||||
const STRATEGY_BTOPT: c_int = 7;
|
||||
|
||||
#[cfg(test)]
|
||||
const BLOCKSIZE_MAX: usize = 1 << 17;
|
||||
#[cfg(test)]
|
||||
const BLOCKSIZE_MAX_MIN: c_int = 1 << 10;
|
||||
const TARGET_C_BLOCK_SIZE_MIN: c_int = 1340;
|
||||
|
||||
@@ -184,34 +178,85 @@ const C_BLOCK_SPLITTER_LEVEL: c_int = 1017;
|
||||
|
||||
#[cfg(not(test))]
|
||||
unsafe extern "C" {
|
||||
fn ZSTD_rust_cctx_params_clamp_bounds(param: c_int, value: *mut c_int) -> usize;
|
||||
fn ZSTD_rust_cctx_params_within_bounds(param: c_int, value: c_int) -> c_int;
|
||||
fn ZSTD_rust_cctx_params_is_multithreaded() -> c_int;
|
||||
fn ZSTD_rust_cctx_params_nb_workers_max() -> c_int;
|
||||
fn ZSTD_rust_cctx_params_job_size_min() -> c_int;
|
||||
fn ZSTD_rust_cctx_params_job_size_max() -> c_int;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct BoundsConfig {
|
||||
multithreaded: bool,
|
||||
nb_workers_max: c_int,
|
||||
job_size_max: c_int,
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
unsafe fn current_bounds_config() -> BoundsConfig {
|
||||
BoundsConfig {
|
||||
multithreaded: unsafe { ZSTD_rust_cctx_params_is_multithreaded() != 0 },
|
||||
nb_workers_max: unsafe { ZSTD_rust_cctx_params_nb_workers_max() },
|
||||
job_size_max: unsafe { ZSTD_rust_cctx_params_job_size_max() },
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn fallback_bounds(param: c_int) -> ZSTD_bounds {
|
||||
unsafe fn current_bounds_config() -> BoundsConfig {
|
||||
BoundsConfig {
|
||||
multithreaded: false,
|
||||
nb_workers_max: 0,
|
||||
job_size_max: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn bounds_for(param: c_int, config: BoundsConfig) -> ZSTD_bounds {
|
||||
let (lower, upper) = match param {
|
||||
C_COMPRESSION_LEVEL | C_WINDOW_LOG | C_HASH_LOG | C_CHAIN_LOG | C_SEARCH_LOG
|
||||
| C_MIN_MATCH | C_TARGET_LENGTH | C_STRATEGY => {
|
||||
return crate::zstd_compress_params::ZSTD_rust_params_getBounds(param)
|
||||
}
|
||||
| C_MIN_MATCH | C_TARGET_LENGTH | C_STRATEGY => return ZSTD_rust_params_getBounds(param),
|
||||
C_FORMAT => (0, 1),
|
||||
C_FORCE_ATTACH_DICT => (0, 3),
|
||||
C_LITERAL_COMPRESSION_MODE => (0, 2),
|
||||
C_CONTENT_SIZE_FLAG | C_CHECKSUM_FLAG | C_DICT_ID_FLAG => (0, 1),
|
||||
C_NB_WORKERS | C_JOB_SIZE | C_OVERLAP_LOG => (0, 0),
|
||||
C_NB_WORKERS => (
|
||||
0,
|
||||
if config.multithreaded {
|
||||
config.nb_workers_max
|
||||
} else {
|
||||
0
|
||||
},
|
||||
),
|
||||
C_JOB_SIZE => (
|
||||
0,
|
||||
if config.multithreaded {
|
||||
config.job_size_max
|
||||
} else {
|
||||
0
|
||||
},
|
||||
),
|
||||
C_OVERLAP_LOG => {
|
||||
if config.multithreaded {
|
||||
(0, 9)
|
||||
} else {
|
||||
(0, 0)
|
||||
}
|
||||
}
|
||||
C_ENABLE_DEDICATED_DICT_SEARCH => (0, 1),
|
||||
C_ENABLE_LDM
|
||||
| C_SPLIT_AFTER_SEQUENCES
|
||||
| C_USE_ROW_MATCH_FINDER
|
||||
| C_PREFETCH_CDICT_TABLES
|
||||
| C_REPCODE_RESOLUTION => (PS_AUTO, PS_DISABLE),
|
||||
C_LDM_HASH_LOG => (6, 30),
|
||||
C_LDM_HASH_LOG => {
|
||||
let bounds = ZSTD_rust_params_getBounds(C_HASH_LOG);
|
||||
(bounds.lowerBound, bounds.upperBound)
|
||||
}
|
||||
C_LDM_MIN_MATCH => (4, 4096),
|
||||
C_LDM_BUCKET_SIZE_LOG => (1, 8),
|
||||
C_LDM_HASH_RATE_LOG => (0, if size_of::<usize>() == 4 { 24 } else { 25 }),
|
||||
C_LDM_HASH_RATE_LOG => {
|
||||
let window_log = ZSTD_rust_params_getBounds(C_WINDOW_LOG);
|
||||
let hash_log = ZSTD_rust_params_getBounds(C_HASH_LOG);
|
||||
(0, window_log.upperBound - hash_log.lowerBound)
|
||||
}
|
||||
C_RSYNCABLE
|
||||
| C_FORCE_MAX_WINDOW
|
||||
| C_VALIDATE_SEQUENCES
|
||||
@@ -237,34 +282,53 @@ fn fallback_bounds(param: c_int) -> ZSTD_bounds {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn current_bounds(param: c_int) -> ZSTD_bounds {
|
||||
bounds_for(param, unsafe { current_bounds_config() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn within_bounds(param: c_int, value: c_int) -> bool {
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
unsafe { ZSTD_rust_cctx_params_within_bounds(param, value) != 0 }
|
||||
}
|
||||
#[cfg(test)]
|
||||
{
|
||||
let bounds = fallback_bounds(param);
|
||||
bounds.error == 0 && value >= bounds.lowerBound && value <= bounds.upperBound
|
||||
within_bounds_for(param, value, unsafe { current_bounds_config() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn within_bounds_for(param: c_int, value: c_int, config: BoundsConfig) -> bool {
|
||||
let bounds = bounds_for(param, config);
|
||||
bounds.error == 0 && value >= bounds.lowerBound && value <= bounds.upperBound
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clamp_bounds_for(param: c_int, value: &mut c_int, config: BoundsConfig) -> usize {
|
||||
let bounds = bounds_for(param, config);
|
||||
if bounds.error != 0 {
|
||||
return bounds.error;
|
||||
}
|
||||
*value = (*value).clamp(bounds.lowerBound, bounds.upperBound);
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn clamp_bounds(param: c_int, value: &mut c_int) -> usize {
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
unsafe { ZSTD_rust_cctx_params_clamp_bounds(param, value) }
|
||||
}
|
||||
#[cfg(test)]
|
||||
{
|
||||
let bounds = fallback_bounds(param);
|
||||
if bounds.error != 0 {
|
||||
return bounds.error;
|
||||
}
|
||||
*value = (*value).clamp(bounds.lowerBound, bounds.upperBound);
|
||||
0
|
||||
}
|
||||
clamp_bounds_for(param, value, unsafe { current_bounds_config() })
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_cctx_params_get_bounds(param: c_int) -> ZSTD_bounds {
|
||||
unsafe { current_bounds(param) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_cctx_params_clamp_bounds(
|
||||
param: c_int,
|
||||
value: *mut c_int,
|
||||
) -> usize {
|
||||
unsafe { clamp_bounds(param, &mut *value) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_cctx_params_within_bounds(param: c_int, value: c_int) -> c_int {
|
||||
unsafe { within_bounds(param, value) as c_int }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -1006,6 +1070,138 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn migrated_non_core_bounds_preserve_pointer_and_thread_configuration() {
|
||||
let single_threaded = BoundsConfig {
|
||||
multithreaded: false,
|
||||
nb_workers_max: 0,
|
||||
job_size_max: 0,
|
||||
};
|
||||
let expected = [
|
||||
(C_FORMAT, 0, 1),
|
||||
(C_FORCE_ATTACH_DICT, 0, 3),
|
||||
(C_LITERAL_COMPRESSION_MODE, 0, 2),
|
||||
(C_CONTENT_SIZE_FLAG, 0, 1),
|
||||
(C_CHECKSUM_FLAG, 0, 1),
|
||||
(C_DICT_ID_FLAG, 0, 1),
|
||||
(C_NB_WORKERS, 0, 0),
|
||||
(C_JOB_SIZE, 0, 0),
|
||||
(C_OVERLAP_LOG, 0, 0),
|
||||
(C_ENABLE_DEDICATED_DICT_SEARCH, 0, 1),
|
||||
(C_ENABLE_LDM, PS_AUTO, PS_DISABLE),
|
||||
(C_LDM_HASH_LOG, 6, 30),
|
||||
(C_LDM_MIN_MATCH, 4, 4096),
|
||||
(C_LDM_BUCKET_SIZE_LOG, 1, 8),
|
||||
(
|
||||
C_LDM_HASH_RATE_LOG,
|
||||
0,
|
||||
if size_of::<usize>() == 4 { 24 } else { 25 },
|
||||
),
|
||||
(C_RSYNCABLE, 0, 1),
|
||||
(C_FORCE_MAX_WINDOW, 0, 1),
|
||||
(C_VALIDATE_SEQUENCES, 0, 1),
|
||||
(C_SPLIT_AFTER_SEQUENCES, PS_AUTO, PS_DISABLE),
|
||||
(C_USE_ROW_MATCH_FINDER, PS_AUTO, PS_DISABLE),
|
||||
(C_DETERMINISTIC_REF_PREFIX, 0, 1),
|
||||
(C_PREFETCH_CDICT_TABLES, PS_AUTO, PS_DISABLE),
|
||||
(C_ENABLE_SEQ_PRODUCER_FALLBACK, 0, 1),
|
||||
(
|
||||
C_TARGET_C_BLOCK_SIZE,
|
||||
TARGET_C_BLOCK_SIZE_MIN,
|
||||
BLOCKSIZE_MAX as c_int,
|
||||
),
|
||||
(C_SRC_SIZE_HINT, 0, c_int::MAX),
|
||||
(C_STABLE_IN_BUFFER, 0, 1),
|
||||
(C_STABLE_OUT_BUFFER, 0, 1),
|
||||
(C_BLOCK_DELIMITERS, 0, 1),
|
||||
(C_BLOCK_SPLITTER_LEVEL, 0, 6),
|
||||
(C_MAX_BLOCK_SIZE, BLOCKSIZE_MAX_MIN, BLOCKSIZE_MAX as c_int),
|
||||
(C_REPCODE_RESOLUTION, PS_AUTO, PS_DISABLE),
|
||||
];
|
||||
|
||||
for (param, lower, upper) in expected {
|
||||
let bounds = bounds_for(param, single_threaded);
|
||||
assert_eq!(bounds.error, 0, "param {param} returned an error");
|
||||
assert_eq!((bounds.lowerBound, bounds.upperBound), (lower, upper));
|
||||
assert!(within_bounds_for(param, lower, single_threaded));
|
||||
assert!(within_bounds_for(param, upper, single_threaded));
|
||||
if lower > c_int::MIN {
|
||||
assert!(!within_bounds_for(param, lower - 1, single_threaded));
|
||||
}
|
||||
if upper < c_int::MAX {
|
||||
assert!(!within_bounds_for(param, upper + 1, single_threaded));
|
||||
}
|
||||
}
|
||||
|
||||
let unsupported = bounds_for(12345, single_threaded);
|
||||
assert_eq!(
|
||||
unsupported.error,
|
||||
ERROR(ZstdErrorCode::ParameterUnsupported)
|
||||
);
|
||||
|
||||
let multithreaded = BoundsConfig {
|
||||
multithreaded: true,
|
||||
nb_workers_max: 17,
|
||||
job_size_max: 987_654_321,
|
||||
};
|
||||
assert_eq!(
|
||||
(
|
||||
bounds_for(C_NB_WORKERS, multithreaded).lowerBound,
|
||||
bounds_for(C_NB_WORKERS, multithreaded).upperBound
|
||||
),
|
||||
(0, 17)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
bounds_for(C_JOB_SIZE, multithreaded).lowerBound,
|
||||
bounds_for(C_JOB_SIZE, multithreaded).upperBound
|
||||
),
|
||||
(0, 987_654_321)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
bounds_for(C_OVERLAP_LOG, multithreaded).lowerBound,
|
||||
bounds_for(C_OVERLAP_LOG, multithreaded).upperBound
|
||||
),
|
||||
(0, 9)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn migrated_clamp_bounds_clamps_and_reports_unsupported_parameters() {
|
||||
let multithreaded = BoundsConfig {
|
||||
multithreaded: true,
|
||||
nb_workers_max: 17,
|
||||
job_size_max: 987_654_321,
|
||||
};
|
||||
|
||||
let mut value = -1;
|
||||
assert_eq!(clamp_bounds_for(C_FORMAT, &mut value, multithreaded), 0);
|
||||
assert_eq!(value, 0);
|
||||
|
||||
value = c_int::MAX;
|
||||
assert_eq!(
|
||||
clamp_bounds_for(C_TARGET_C_BLOCK_SIZE, &mut value, multithreaded),
|
||||
0
|
||||
);
|
||||
assert_eq!(value, BLOCKSIZE_MAX as c_int);
|
||||
|
||||
value = c_int::MAX;
|
||||
assert_eq!(clamp_bounds_for(C_NB_WORKERS, &mut value, multithreaded), 0);
|
||||
assert_eq!(value, 17);
|
||||
|
||||
value = -1;
|
||||
assert_eq!(clamp_bounds_for(C_JOB_SIZE, &mut value, multithreaded), 0);
|
||||
assert_eq!(value, 0);
|
||||
|
||||
value = -1;
|
||||
assert_eq!(
|
||||
clamp_bounds_for(12345, &mut value, multithreaded),
|
||||
ERROR(ZstdErrorCode::ParameterUnsupported)
|
||||
);
|
||||
assert_eq!(value, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advanced_init_resolves_policy_and_resets_internal_fields() {
|
||||
let cases = [
|
||||
|
||||
Reference in New Issue
Block a user