feat(compress): project end continue state into Rust

Share the synchronous compressContinue projection with the end-of-frame
orchestration so Rust calls the migrated continue path directly. Remove the
redundant C end callback while retaining the C trace callback and the
context-sensitive compression leaves.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --all -- --check
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --lib zstd_compress::tests::compress_end -- --nocapture
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --all-targets -- -D warnings
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s
- ulimit -v 41943040; make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
This commit is contained in:
2026-07-20 00:57:46 +02:00
parent 58e6d2eef7
commit 0a69df20a3
2 changed files with 289 additions and 152 deletions
+110 -111
View File
@@ -954,21 +954,14 @@ typedef char ZSTD_rust_compress_continue_state_layout[
== (sizeof(void*) == 8 ? 120 : 80))
? 1 : -1];
/* Rust owns the end-of-frame orchestration. The callbacks retain the
* private CCtx-dependent continue and trace operations in C; checksum and
* frame-epilogue fields are projected explicitly. */
typedef size_t (*ZSTD_rust_compressEndContinue_f)(void* context,
void* dst,
size_t dstCapacity,
const void* src,
size_t srcSize,
U32 frame,
U32 lastFrameChunk);
/* Rust owns the end-of-frame orchestration. Only the trace operation still
* needs a callback; checksum and frame-epilogue fields are projected
* explicitly, and continue uses the shared direct state projection. */
typedef void (*ZSTD_rust_compressEndTrace_f)(void* context,
size_t extraCSize);
typedef struct {
void* callbackContext;
ZSTD_rust_compressEndContinue_f compressContinue;
const ZSTD_rust_compressContinueState* compressContinueState;
ZSTD_rust_compressEndTrace_f trace;
unsigned long long* consumedSrcSize;
U64 pledgedSrcSizePlusOne;
@@ -985,7 +978,7 @@ size_t ZSTD_rust_compressEnd(const ZSTD_rust_compressEndState* state,
const void* src, size_t srcSize);
typedef char ZSTD_rust_compress_end_state_layout[
(offsetof(ZSTD_rust_compressEndState, callbackContext) == 0
&& offsetof(ZSTD_rust_compressEndState, compressContinue)
&& offsetof(ZSTD_rust_compressEndState, compressContinueState)
== sizeof(void*)
&& offsetof(ZSTD_rust_compressEndState, trace)
== 2 * sizeof(void*)
@@ -5432,6 +5425,20 @@ typedef struct {
const ZSTD_CCtx_params* params;
} ZSTD_rust_overflowCorrectContext;
/* All continue entry points use this synchronous stack projection. The
* private CCtx and match-state layouts remain behind the direct field
* projections and context-sensitive leaf callbacks. */
typedef struct {
ZSTD_rust_compressContinueState state;
ZSTD_rust_compressContinueWindowState windowState;
ZSTD_rust_compressContinueWindowState ldmWindowState;
ZSTD_rust_frameChunkState frameChunkState;
ZSTD_rust_frameChunkPrepareState frameChunkPrepareState;
ZSTD_rust_frameChunkClampState frameChunkClampState;
ZSTD_rust_overflowCorrectContext overflowContext;
ZSTD_rust_overflowCorrectState overflowState;
} ZSTD_rust_compressContinueContext;
static int ZSTD_rust_overflowCorrect_need(
void* context, const void* src, const void* srcEnd)
{
@@ -5579,100 +5586,100 @@ static size_t ZSTD_rust_compressContinue_block(
0 /* frame */);
}
static void ZSTD_compressContinue_prepare(
ZSTD_CCtx* cctx, size_t blockSizeMax, int checkBlockSize,
ZSTD_rust_compressContinueContext* context)
{
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
ZSTD_window_t* const window = &ms->window;
ZSTD_window_t* const ldmWindow = &cctx->ldmState.window;
context->windowState.nextSrc = &window->nextSrc;
context->windowState.base = &window->base;
context->windowState.dictBase = &window->dictBase;
context->windowState.dictLimit = &window->dictLimit;
context->windowState.lowLimit = &window->lowLimit;
context->windowState.forceNonContiguous = &ms->forceNonContiguous;
context->windowState.nextToUpdate = &ms->nextToUpdate;
context->ldmWindowState.nextSrc = &ldmWindow->nextSrc;
context->ldmWindowState.base = &ldmWindow->base;
context->ldmWindowState.dictBase = &ldmWindow->dictBase;
context->ldmWindowState.dictLimit = &ldmWindow->dictLimit;
context->ldmWindowState.lowLimit = &ldmWindow->lowLimit;
context->ldmWindowState.forceNonContiguous = NULL;
context->ldmWindowState.nextToUpdate = NULL;
context->frameChunkPrepareState.callbackContext = cctx;
context->frameChunkPrepareState.maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
context->frameChunkPrepareState.correctOverflow = ZSTD_rust_frameChunk_correctOverflow;
context->frameChunkPrepareState.checkDictValidity = ZSTD_rust_frameChunk_checkDictValidity;
context->frameChunkPrepareState.enforceMaxDist = ZSTD_rust_frameChunk_enforceMaxDist;
context->frameChunkClampState.nextToUpdate = &ms->nextToUpdate;
context->frameChunkClampState.lowLimit = &ms->window.lowLimit;
context->frameChunkPrepareState.clampState = &context->frameChunkClampState;
context->frameChunkState.callbackContext = cctx;
context->frameChunkState.tmpWorkspace = cctx->tmpWorkspace;
context->frameChunkState.checksumState = &cctx->xxhState;
context->frameChunkState.isFirstBlock = &cctx->isFirstBlock;
context->frameChunkState.stage = &cctx->stage;
context->frameChunkState.tmpWkspSize = cctx->tmpWkspSize;
context->frameChunkState.blockSizeMax = cctx->blockSizeMax;
context->frameChunkState.savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize;
context->frameChunkState.preBlockSplitterLevel = cctx->appliedParams.preBlockSplitter_level;
context->frameChunkState.strategy = (int)cctx->appliedParams.cParams.strategy;
context->frameChunkState.useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams);
context->frameChunkState.blockSplitterEnabled = ZSTD_blockSplitterEnabled(&cctx->appliedParams);
context->frameChunkState.checksumFlag = cctx->appliedParams.fParams.checksumFlag;
context->frameChunkState.endingStage = (int)ZSTDcs_ending;
context->frameChunkState.prepareState = &context->frameChunkPrepareState;
context->frameChunkState.compressTarget = ZSTD_rust_frameChunk_compressTarget;
context->frameChunkState.compressSplit = ZSTD_rust_frameChunk_compressSplit;
context->frameChunkState.compressInternal = ZSTD_rust_frameChunk_compressInternal;
context->overflowContext.matchState = ms;
context->overflowContext.workspace = &cctx->workspace;
context->overflowContext.params = &cctx->appliedParams;
context->overflowState.callbackContext = &context->overflowContext;
context->overflowState.nextToUpdate = &ms->nextToUpdate;
context->overflowState.needCorrection = ZSTD_rust_overflowCorrect_need;
context->overflowState.correctOverflow = ZSTD_rust_overflowCorrect_correct;
context->overflowState.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty;
context->overflowState.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex;
context->overflowState.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean;
context->overflowState.loadedDictEnd = &ms->loadedDictEnd;
context->overflowState.dictMatchState = &ms->dictMatchState;
context->state.callbackContext = cctx;
context->state.windowState = &context->windowState;
context->state.ldmWindowState = &context->ldmWindowState;
context->state.overflowState = &context->overflowState;
context->state.frameChunkState = &context->frameChunkState;
context->state.compressBlock = ZSTD_rust_compressContinue_block;
context->state.stage = &cctx->stage;
context->state.consumedSrcSize = &cctx->consumedSrcSize;
context->state.producedCSize = &cctx->producedCSize;
context->state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne;
context->state.blockSizeMax = blockSizeMax;
context->state.checkBlockSize = checkBlockSize;
context->state.noDictIDFlag = cctx->appliedParams.fParams.noDictIDFlag;
context->state.checksumFlag = cctx->appliedParams.fParams.checksumFlag;
context->state.contentSizeFlag = cctx->appliedParams.fParams.contentSizeFlag;
context->state.format = (int)cctx->appliedParams.format;
context->state.windowLog = cctx->appliedParams.cParams.windowLog;
context->state.dictID = cctx->dictID;
context->state.ldmEnabled = cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable;
}
static size_t ZSTD_compressContinue_dispatch(
ZSTD_CCtx* cctx, void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
U32 frame, U32 lastFrameChunk,
size_t blockSizeMax, int checkBlockSize)
{
ZSTD_rust_compressContinueState state;
ZSTD_rust_compressContinueWindowState windowState;
ZSTD_rust_compressContinueWindowState ldmWindowState;
ZSTD_rust_frameChunkState frameChunkState;
ZSTD_rust_frameChunkPrepareState frameChunkPrepareState;
ZSTD_rust_frameChunkClampState frameChunkClampState;
ZSTD_rust_overflowCorrectContext overflowContext;
ZSTD_rust_overflowCorrectState overflowState;
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
ZSTD_window_t* const window = &ms->window;
ZSTD_window_t* const ldmWindow = &cctx->ldmState.window;
windowState.nextSrc = &window->nextSrc;
windowState.base = &window->base;
windowState.dictBase = &window->dictBase;
windowState.dictLimit = &window->dictLimit;
windowState.lowLimit = &window->lowLimit;
windowState.forceNonContiguous = &ms->forceNonContiguous;
windowState.nextToUpdate = &ms->nextToUpdate;
ldmWindowState.nextSrc = &ldmWindow->nextSrc;
ldmWindowState.base = &ldmWindow->base;
ldmWindowState.dictBase = &ldmWindow->dictBase;
ldmWindowState.dictLimit = &ldmWindow->dictLimit;
ldmWindowState.lowLimit = &ldmWindow->lowLimit;
ldmWindowState.forceNonContiguous = NULL;
ldmWindowState.nextToUpdate = NULL;
frameChunkPrepareState.callbackContext = cctx;
frameChunkPrepareState.maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
frameChunkPrepareState.correctOverflow = ZSTD_rust_frameChunk_correctOverflow;
frameChunkPrepareState.checkDictValidity = ZSTD_rust_frameChunk_checkDictValidity;
frameChunkPrepareState.enforceMaxDist = ZSTD_rust_frameChunk_enforceMaxDist;
frameChunkClampState.nextToUpdate = &ms->nextToUpdate;
frameChunkClampState.lowLimit = &ms->window.lowLimit;
frameChunkPrepareState.clampState = &frameChunkClampState;
frameChunkState.callbackContext = cctx;
frameChunkState.tmpWorkspace = cctx->tmpWorkspace;
frameChunkState.checksumState = &cctx->xxhState;
frameChunkState.isFirstBlock = &cctx->isFirstBlock;
frameChunkState.stage = &cctx->stage;
frameChunkState.tmpWkspSize = cctx->tmpWkspSize;
frameChunkState.blockSizeMax = cctx->blockSizeMax;
frameChunkState.savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize;
frameChunkState.preBlockSplitterLevel = cctx->appliedParams.preBlockSplitter_level;
frameChunkState.strategy = (int)cctx->appliedParams.cParams.strategy;
frameChunkState.useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams);
frameChunkState.blockSplitterEnabled = ZSTD_blockSplitterEnabled(&cctx->appliedParams);
frameChunkState.checksumFlag = cctx->appliedParams.fParams.checksumFlag;
frameChunkState.endingStage = (int)ZSTDcs_ending;
frameChunkState.prepareState = &frameChunkPrepareState;
frameChunkState.compressTarget = ZSTD_rust_frameChunk_compressTarget;
frameChunkState.compressSplit = ZSTD_rust_frameChunk_compressSplit;
frameChunkState.compressInternal = ZSTD_rust_frameChunk_compressInternal;
overflowContext.matchState = ms;
overflowContext.workspace = &cctx->workspace;
overflowContext.params = &cctx->appliedParams;
overflowState.callbackContext = &overflowContext;
overflowState.nextToUpdate = &ms->nextToUpdate;
overflowState.needCorrection = ZSTD_rust_overflowCorrect_need;
overflowState.correctOverflow = ZSTD_rust_overflowCorrect_correct;
overflowState.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty;
overflowState.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex;
overflowState.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean;
overflowState.loadedDictEnd = &ms->loadedDictEnd;
overflowState.dictMatchState = &ms->dictMatchState;
state.callbackContext = cctx;
state.windowState = &windowState;
state.ldmWindowState = &ldmWindowState;
state.overflowState = &overflowState;
state.frameChunkState = &frameChunkState;
state.compressBlock = ZSTD_rust_compressContinue_block;
state.stage = &cctx->stage;
state.consumedSrcSize = &cctx->consumedSrcSize;
state.producedCSize = &cctx->producedCSize;
state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne;
state.blockSizeMax = blockSizeMax;
state.checkBlockSize = checkBlockSize;
state.noDictIDFlag = cctx->appliedParams.fParams.noDictIDFlag;
state.checksumFlag = cctx->appliedParams.fParams.checksumFlag;
state.contentSizeFlag = cctx->appliedParams.fParams.contentSizeFlag;
state.format = (int)cctx->appliedParams.format;
state.windowLog = cctx->appliedParams.cParams.windowLog;
state.dictID = cctx->dictID;
state.ldmEnabled = cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable;
ZSTD_rust_compressContinueContext context;
ZSTD_compressContinue_prepare(cctx, blockSizeMax, checkBlockSize, &context);
return ZSTD_rust_compressContinue(
&state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk);
&context.state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk);
}
void ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
@@ -6178,17 +6185,6 @@ void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
#endif
}
static size_t ZSTD_rust_compressEnd_continue(
void* context, void* dst, size_t dstCapacity,
const void* src, size_t srcSize, U32 frame, U32 lastFrameChunk)
{
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
return ZSTD_compressContinue_dispatch(
cctx, dst, dstCapacity, src, srcSize,
frame, lastFrameChunk, cctx->blockSizeMax,
0 /* block size already selected */);
}
static void ZSTD_rust_compressEnd_trace(void* context, size_t extraCSize)
{
ZSTD_CCtx_trace((ZSTD_CCtx*)context, extraCSize);
@@ -6198,9 +6194,12 @@ size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
ZSTD_rust_compressContinueContext continueContext;
ZSTD_rust_compressEndState state;
ZSTD_compressContinue_prepare(cctx, cctx->blockSizeMax,
0 /* block size already selected */, &continueContext);
state.callbackContext = cctx;
state.compressContinue = ZSTD_rust_compressEnd_continue;
state.compressContinueState = &continueContext.state;
state.trace = ZSTD_rust_compressEnd_trace;
state.consumedSrcSize = &cctx->consumedSrcSize;
state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne;