feat(cdict): move table-load policy into Rust

CDict initialization already routes content copying and dictionary insertion
through the Rust orchestrator, but its private C adapter still hard-coded the
full table-load method and the CDict table-fill purpose. That split left an
important advanced-CDict content-loading policy hidden in the C bridge and
made the callback contract less explicit.

Extend the private insertion callback with the two table-loading policy
values. Rust now selects the full-load and for-CDict modes after its content
branch and before invoking the opaque C operation. C retains only the private
CDict layout projection and forwards those selected values to the existing
content loader, preserving the original insertion order and behavior.

The focused initialization probes record both values in the callback and
assert them for by-reference and by-copy dictionaries alongside the existing
ordering and content-copy checks.

Test Plan:
- `rustfmt +nightly --edition 2021 --check rust/src/zstd_compress_dictionary.rs` -- passed
- `ulimit -v 41943040; gcc -fsyntax-only -std=c99 -DXXH_NAMESPACE=ZSTD_ -DDEBUGLEVEL=0 -DZSTD_MULTITHREAD -DZSTD_LEGACY_SUPPORT=5 -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/deprecated lib/compress/zstd_compress.c` -- passed
- `ulimit -v 41943040; clang -fsyntax-only -std=c99 -DXXH_NAMESPACE=ZSTD_ -DDEBUGLEVEL=0 -DZSTD_MULTITHREAD -DZSTD_LEGACY_SUPPORT=5 -DZSTD_NO_ASM=1 -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/deprecated lib/compress/zstd_compress.c` -- passed
- `git diff --check` and `git diff --cached --check` -- passed
- Cargo, make, native builds, fuzzers, and large tests were not run per task constraints
This commit is contained in:
2026-07-20 16:44:31 +02:00
parent 1b1b540e1f
commit e79a086d7b
2 changed files with 33 additions and 10 deletions
+5 -4
View File
@@ -2645,7 +2645,7 @@ typedef size_t (*ZSTD_rust_initCDictResetMatchState_f)(
int useRowMatchFinder);
typedef size_t (*ZSTD_rust_initCDictInsertDictionary_f)(
void* context, const void* params, const void* dict,
size_t dictSize, int dictContentType);
size_t dictSize, int dictContentType, int dtlm, int tfp);
typedef struct {
void* callbackContext;
void* params;
@@ -6446,14 +6446,15 @@ static size_t ZSTD_rust_initCDict_resetMatchState(
static size_t ZSTD_rust_initCDict_insertDictionary(
void* context, const void* params, const void* dict,
size_t dictSize, int dictContentType)
size_t dictSize, int dictContentType, int dtlm, int tfp)
{
ZSTD_CDict* const cdict = (ZSTD_CDict*)context;
return ZSTD_compress_insertDictionary(
&cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
(const ZSTD_CCtx_params*)params, dict, dictSize,
(ZSTD_dictContentType_e)dictContentType, ZSTD_dtlm_full,
ZSTD_tfp_forCDict, cdict->entropyWorkspace);
(ZSTD_dictContentType_e)dictContentType,
(ZSTD_dictTableLoadMethod_e)dtlm,
(ZSTD_tableFillPurpose_e)tfp, cdict->entropyWorkspace);
}
static size_t ZSTD_rust_compressBegin_resetInternal(
+28 -6
View File
@@ -45,6 +45,7 @@ const ZSTD_MAGIC_DICTIONARY: u32 = 0xEC30_A437;
const ZSTD_DCT_AUTO: c_int = 0;
const ZSTD_DCT_RAW_CONTENT: c_int = 1;
const ZSTD_DCT_FULL_DICT: c_int = 2;
const ZSTD_DTL_FULL: c_int = 1;
const ZSTD_STATIC_WORKSPACE_ALIGNMENT: usize = 8;
/// C keeps match-state/content insertion private because it depends on the
@@ -1242,15 +1243,22 @@ pub unsafe extern "C" fn ZSTD_rust_compressBeginUsingDict(
type InitCDictReserveContentFn = unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void;
type InitCDictReserveEntropyFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void;
type InitCDictResetMatchStateFn = unsafe extern "C" fn(*mut c_void, *const c_void, c_int) -> usize;
type InitCDictInsertDictionaryFn =
unsafe extern "C" fn(*mut c_void, *const c_void, *const c_void, usize, c_int) -> usize;
type InitCDictInsertDictionaryFn = unsafe extern "C" fn(
*mut c_void,
*const c_void,
*const c_void,
usize,
c_int,
c_int,
c_int,
) -> usize;
/// Projection for CDict content/state initialization.
///
/// Rust owns the content branch/copy, initialization order, and scalar field
/// policy. C callbacks retain private workspace allocation, match-state reset,
/// and dictionary insertion because those operations use private CDict
/// layouts.
/// Rust owns the content branch/copy, table-loading policy, initialization
/// order, and scalar field policy. C callbacks retain private workspace
/// allocation, match-state reset, and dictionary insertion because those
/// operations use private CDict layouts.
#[repr(C)]
pub struct ZSTD_rust_initCDictState {
callback_context: *mut c_void,
@@ -1402,6 +1410,8 @@ pub unsafe extern "C" fn ZSTD_rust_initCDict(
dict_content,
dict_size,
dict_content_type,
ZSTD_DTL_FULL,
ZSTD_TFP_FOR_CDICT as c_int,
)
};
if ERR_isError(dict_id) {
@@ -2614,6 +2624,8 @@ mod tests {
inserted_dict: *const c_void,
inserted_size: usize,
inserted_content_type: c_int,
inserted_dtlm: c_int,
inserted_tfp: c_int,
entropy_workspace: *mut c_void,
reset_match_result: usize,
insert_result: usize,
@@ -2632,6 +2644,8 @@ mod tests {
inserted_dict: ptr::null(),
inserted_size: 0,
inserted_content_type: 0,
inserted_dtlm: 0,
inserted_tfp: 0,
entropy_workspace: ptr::null_mut(),
reset_match_result: 0,
insert_result: 0,
@@ -2681,6 +2695,8 @@ mod tests {
dict: *const c_void,
dict_size: usize,
dict_content_type: c_int,
dtlm: c_int,
tfp: c_int,
) -> usize {
let probe = unsafe { init_cdict_probe(context) };
probe.events.push("insert");
@@ -2688,6 +2704,8 @@ mod tests {
probe.inserted_dict = dict;
probe.inserted_size = dict_size;
probe.inserted_content_type = dict_content_type;
probe.inserted_dtlm = dtlm;
probe.inserted_tfp = tfp;
probe.insert_result
}
@@ -2764,6 +2782,8 @@ mod tests {
assert_eq!(probe.inserted_dict, dictionary.as_ptr().cast());
assert_eq!(probe.inserted_size, dictionary.len());
assert_eq!(probe.inserted_content_type, ZSTD_DCT_RAW_CONTENT);
assert_eq!(probe.inserted_dtlm, ZSTD_DTL_FULL);
assert_eq!(probe.inserted_tfp, ZSTD_TFP_FOR_CDICT as c_int);
assert_eq!(match_state_c_params, c_params);
assert_eq!(dedicated_dict_search, enable_dedicated_dict_search);
assert_eq!(dict_content_size, dictionary.len());
@@ -2850,6 +2870,8 @@ mod tests {
assert_eq!(dict_content, probe.content_storage.as_ptr().cast());
assert_eq!(probe.inserted_dict, dict_content);
assert_eq!(dict_content_size, dictionary.len());
assert_eq!(probe.inserted_dtlm, ZSTD_DTL_FULL);
assert_eq!(probe.inserted_tfp, ZSTD_TFP_FOR_CDICT as c_int);
}
struct CompressBeginProbe {