feat(compress): move dictionary dispatch into Rust
Dictionary insertion still kept its high-level policy in zstd_compress.c: short and missing dictionary handling, content-type selection, magic and dictionary-ID processing, entropy-header loading, and compressed-block-state reset were all interleaved with the private match-state content loader. Move that dispatch into ZSTD_rust_compressInsertDictionary. Rust now owns the mode decisions, reset ordering, dictionary magic and ID semantics, entropy loading, and error propagation. C retains only a narrow opaque callback for ZSTD_loadDictionaryContent because that operation depends on private ZSTD_MatchState_t, ldmState_t, workspace, and parameter layouts. The focused Rust tests cover short/full errors, raw and auto callback selection, full dictionary entropy loading, and noDictIDFlag behavior. Test Plan: - `cargo test --manifest-path rust/Cargo.toml dictionary -- --test-threads=1` -- 21 passed under the 40 GiB virtual-memory cap. - `cargo test --manifest-path rust/Cargo.toml --all-targets -- --test-threads=1` -- 513 passed under the cap before the test-only clippy sentinel cleanup; the focused dictionary suite passed again on the exact staged contents. - `cargo clippy` lib/benches/tests for `rust` and `rust/cli`, with `-D warnings`, and nightly formatting -- passed. - Native library, CLI, full zstd, fuzzer, zstream, and decode-corpus targets -- passed serially under the cap. GPG signing was attempted but unavailable because no pinentry process was available; this repository's preceding commits are unsigned, so this commit uses the explicit unsigned fallback.
This commit is contained in:
@@ -688,6 +688,19 @@ U32 ZSTD_rust_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM],
|
||||
U32 offBase, U32 ll0);
|
||||
size_t ZSTD_rust_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
||||
const void* dict, size_t dictSize);
|
||||
/* Rust owns dictionary-ingestion policy. The content loader remains a narrow
|
||||
* callback because it needs configuration-sensitive C-private layouts. */
|
||||
typedef size_t (*ZSTD_rust_loadDictionaryContent_f)(
|
||||
void* matchState, void* ldmState, void* workspaceState,
|
||||
const void* params, const void* src, size_t srcSize,
|
||||
int dtlm, int tfp);
|
||||
size_t ZSTD_rust_compressInsertDictionary(
|
||||
ZSTD_compressedBlockState_t* bs,
|
||||
void* matchState, void* ldmState, void* workspaceState,
|
||||
const void* params, const void* dict, size_t dictSize,
|
||||
int dictContentType, int dtlm, int tfp,
|
||||
void* workspace, int noDictIDFlag,
|
||||
ZSTD_rust_loadDictionaryContent_f loadDictionaryContent);
|
||||
size_t ZSTD_rust_transferSequencesWBlockDelim(
|
||||
SeqStore_t* seqStore, ZSTD_SequencePosition* seqPos,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
@@ -3566,43 +3579,21 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
||||
return ZSTD_rust_loadCEntropy(bs, workspace, dict, dictSize);
|
||||
}
|
||||
|
||||
/* Dictionary format :
|
||||
* See :
|
||||
* https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format
|
||||
*/
|
||||
/*! ZSTD_loadZstdDictionary() :
|
||||
* @return : dictID, or an error code
|
||||
* assumptions : magic number supposed already checked
|
||||
* dictSize supposed >= 8
|
||||
*/
|
||||
static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
||||
ZSTD_MatchState_t* ms,
|
||||
ZSTD_cwksp* ws,
|
||||
ZSTD_CCtx_params const* params,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictTableLoadMethod_e dtlm,
|
||||
ZSTD_tableFillPurpose_e tfp,
|
||||
void* workspace)
|
||||
/* Keep the match-state/content operation private to C. Rust passes only
|
||||
* opaque pointers here after it has selected the dictionary path. */
|
||||
static size_t ZSTD_loadDictionaryContent_callback(
|
||||
void* matchState, void* ldmState, void* workspaceState,
|
||||
const void* params, const void* src, size_t srcSize,
|
||||
int dtlm, int tfp)
|
||||
{
|
||||
const BYTE* dictPtr = (const BYTE*)dict;
|
||||
const BYTE* const dictEnd = dictPtr + dictSize;
|
||||
size_t dictID;
|
||||
size_t eSize;
|
||||
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
|
||||
assert(dictSize >= 8);
|
||||
assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
|
||||
|
||||
dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ );
|
||||
eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);
|
||||
FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
|
||||
dictPtr += eSize;
|
||||
|
||||
{
|
||||
size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
|
||||
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
|
||||
ms, NULL, ws, params, dictPtr, dictContentSize, dtlm, tfp), "");
|
||||
}
|
||||
return dictID;
|
||||
return ZSTD_loadDictionaryContent(
|
||||
(ZSTD_MatchState_t*)matchState,
|
||||
(ldmState_t*)ldmState,
|
||||
(ZSTD_cwksp*)workspaceState,
|
||||
(const ZSTD_CCtx_params*)params,
|
||||
src, srcSize,
|
||||
(ZSTD_dictTableLoadMethod_e)dtlm,
|
||||
(ZSTD_tableFillPurpose_e)tfp);
|
||||
}
|
||||
|
||||
/** ZSTD_compress_insertDictionary() :
|
||||
@@ -3619,31 +3610,15 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
||||
ZSTD_tableFillPurpose_e tfp,
|
||||
void* workspace)
|
||||
{
|
||||
int const noDictIDFlag = (params != NULL && dict != NULL && dictSize >= 8)
|
||||
? params->fParams.noDictIDFlag
|
||||
: 0;
|
||||
DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
|
||||
if ((dict==NULL) || (dictSize<8)) {
|
||||
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZSTD_reset_compressedBlockState(bs);
|
||||
|
||||
/* dict restricted modes */
|
||||
if (dictContentType == ZSTD_dct_rawContent)
|
||||
return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm, tfp);
|
||||
|
||||
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
|
||||
if (dictContentType == ZSTD_dct_auto) {
|
||||
DEBUGLOG(4, "raw content dictionary detected");
|
||||
return ZSTD_loadDictionaryContent(
|
||||
ms, ls, ws, params, dict, dictSize, dtlm, tfp);
|
||||
}
|
||||
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
|
||||
assert(0); /* impossible */
|
||||
}
|
||||
|
||||
/* dict as full zstd dictionary */
|
||||
return ZSTD_loadZstdDictionary(
|
||||
bs, ms, ws, params, dict, dictSize, dtlm, tfp, workspace);
|
||||
return ZSTD_rust_compressInsertDictionary(
|
||||
bs, ms, ls, ws, params, dict, dictSize,
|
||||
(int)dictContentType, (int)dtlm, (int)tfp,
|
||||
workspace, noDictIDFlag,
|
||||
ZSTD_loadDictionaryContent_callback);
|
||||
}
|
||||
|
||||
#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
|
||||
|
||||
Reference in New Issue
Block a user