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:
2026-07-18 03:38:56 +02:00
parent 65bfc6bb2b
commit 6aaabce208
2 changed files with 259 additions and 251 deletions
+24 -212
View File
@@ -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), \