feat(compress): move overflow scalar cleanup into Rust

Keep overflow correction's window and table operations behind C callbacks, but
project the remaining dictionary invalidation fields directly so Rust owns the
entire correction order.  Replace frame-chunk's scalar next-to-update clamp
callback with a checked pointer projection, leaving the private window checks
and block callbacks in C.

Test Plan:
- cargo fmt --manifest-path rust/Cargo.toml -- --check
- CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml overflow_correction
- CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml frame_chunk_
- CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- make -j1
- make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s
- make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
- CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml
This commit is contained in:
2026-07-19 21:22:12 +02:00
parent 9d8c03d87d
commit 56c8cd5384
2 changed files with 86 additions and 53 deletions
+23 -25
View File
@@ -677,7 +677,8 @@ typedef struct {
ZSTD_rust_overflowCallback_f markTablesDirty;
ZSTD_rust_overflowReduceIndex_f reduceIndex;
ZSTD_rust_overflowCallback_f markTablesClean;
ZSTD_rust_overflowCallback_f invalidateDictionary;
U32* loadedDictEnd;
const ZSTD_MatchState_t** dictMatchState;
} ZSTD_rust_overflowCorrectState;
void ZSTD_rust_overflowCorrectIfNeeded(
const ZSTD_rust_overflowCorrectState* state,
@@ -690,8 +691,9 @@ typedef char ZSTD_rust_overflow_correct_state_layout[
&& offsetof(ZSTD_rust_overflowCorrectState, markTablesDirty) == 4 * sizeof(void*)
&& offsetof(ZSTD_rust_overflowCorrectState, reduceIndex) == 5 * sizeof(void*)
&& offsetof(ZSTD_rust_overflowCorrectState, markTablesClean) == 6 * sizeof(void*)
&& offsetof(ZSTD_rust_overflowCorrectState, invalidateDictionary) == 7 * sizeof(void*)
&& sizeof(ZSTD_rust_overflowCorrectState) == 8 * sizeof(void*))
&& offsetof(ZSTD_rust_overflowCorrectState, loadedDictEnd) == 7 * sizeof(void*)
&& offsetof(ZSTD_rust_overflowCorrectState, dictMatchState) == 8 * sizeof(void*)
&& sizeof(ZSTD_rust_overflowCorrectState) == 9 * sizeof(void*))
? 1 : -1];
void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src,
size_t tableSize, int tagged);
@@ -768,15 +770,23 @@ typedef void (*ZSTD_rust_frameChunkPrepareWindow_f)(void* context,
const void* src,
size_t blockSize,
U32 maxDist);
typedef void (*ZSTD_rust_frameChunkPrepareClamp_f)(void* context);
typedef struct {
U32* nextToUpdate;
const U32* lowLimit;
} ZSTD_rust_frameChunkClampState;
typedef struct {
void* callbackContext;
U32 maxDist;
ZSTD_rust_frameChunkPrepareOverflow_f correctOverflow;
ZSTD_rust_frameChunkPrepareWindow_f checkDictValidity;
ZSTD_rust_frameChunkPrepareWindow_f enforceMaxDist;
ZSTD_rust_frameChunkPrepareClamp_f clampNextToUpdate;
const ZSTD_rust_frameChunkClampState* clampState;
} ZSTD_rust_frameChunkPrepareState;
typedef char ZSTD_rust_frame_chunk_clamp_state_layout[
(offsetof(ZSTD_rust_frameChunkClampState, nextToUpdate) == 0
&& offsetof(ZSTD_rust_frameChunkClampState, lowLimit) == sizeof(void*)
&& sizeof(ZSTD_rust_frameChunkClampState) == 2 * sizeof(void*))
? 1 : -1];
typedef char ZSTD_rust_frame_chunk_prepare_state_layout[
(offsetof(ZSTD_rust_frameChunkPrepareState, callbackContext) == 0
&& offsetof(ZSTD_rust_frameChunkPrepareState, maxDist) == sizeof(void*)
@@ -786,7 +796,7 @@ typedef char ZSTD_rust_frame_chunk_prepare_state_layout[
== 3 * sizeof(void*)
&& offsetof(ZSTD_rust_frameChunkPrepareState, enforceMaxDist)
== 4 * sizeof(void*)
&& offsetof(ZSTD_rust_frameChunkPrepareState, clampNextToUpdate)
&& offsetof(ZSTD_rust_frameChunkPrepareState, clampState)
== 5 * sizeof(void*)
&& sizeof(ZSTD_rust_frameChunkPrepareState) == 6 * sizeof(void*))
? 1 : -1];
@@ -5405,14 +5415,6 @@ static void ZSTD_rust_overflowCorrect_markTablesClean(void* context)
ZSTD_cwksp_mark_tables_clean(state->workspace);
}
static void ZSTD_rust_overflowCorrect_invalidateDictionary(void* context)
{
ZSTD_rust_overflowCorrectContext const* const state =
(const ZSTD_rust_overflowCorrectContext*)context;
state->matchState->loadedDictEnd = 0;
state->matchState->dictMatchState = NULL;
}
static void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms,
ZSTD_cwksp* ws,
ZSTD_CCtx_params const* params,
@@ -5434,7 +5436,8 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms,
state.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty;
state.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex;
state.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean;
state.invalidateDictionary = ZSTD_rust_overflowCorrect_invalidateDictionary;
state.loadedDictEnd = &ms->loadedDictEnd;
state.dictMatchState = &ms->dictMatchState;
ZSTD_rust_overflowCorrectIfNeeded(&state, ip, iend);
}
@@ -5476,15 +5479,6 @@ static void ZSTD_rust_frameChunk_enforceMaxDist(void* context,
(void)blockSize;
}
static void ZSTD_rust_frameChunk_clampNextToUpdate(void* context)
{
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
/* Ensure hash/chain table insertion resumes no sooner than lowlimit. */
if (ms->nextToUpdate < ms->window.lowLimit)
ms->nextToUpdate = ms->window.lowLimit;
}
static size_t ZSTD_rust_frameChunk_compressTarget(
void* context, void* dst, size_t dstCapacity,
const void* src, size_t srcSize, U32 lastBlock)
@@ -5531,12 +5525,16 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
{
ZSTD_rust_frameChunkState state;
ZSTD_rust_frameChunkPrepareState prepareState;
ZSTD_rust_frameChunkClampState clampState;
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
prepareState.callbackContext = cctx;
prepareState.maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
prepareState.correctOverflow = ZSTD_rust_frameChunk_correctOverflow;
prepareState.checkDictValidity = ZSTD_rust_frameChunk_checkDictValidity;
prepareState.enforceMaxDist = ZSTD_rust_frameChunk_enforceMaxDist;
prepareState.clampNextToUpdate = ZSTD_rust_frameChunk_clampNextToUpdate;
clampState.nextToUpdate = &ms->nextToUpdate;
clampState.lowLimit = &ms->window.lowLimit;
prepareState.clampState = &clampState;
state.callbackContext = cctx;
state.tmpWorkspace = cctx->tmpWorkspace;
state.checksumState = &cctx->xxhState;