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:
+110
-111
@@ -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;
|
||||
|
||||
+179
-41
@@ -1146,27 +1146,18 @@ pub unsafe extern "C" fn ZSTD_rust_compressContinue(
|
||||
}
|
||||
}
|
||||
|
||||
type CompressEndContinueFn = unsafe extern "C" fn(
|
||||
*mut c_void,
|
||||
*mut c_void,
|
||||
usize,
|
||||
*const c_void,
|
||||
usize,
|
||||
c_uint,
|
||||
c_uint,
|
||||
) -> usize;
|
||||
type CompressEndTraceFn = unsafe extern "C" fn(*mut c_void, usize);
|
||||
|
||||
/// Explicit projection for the public end-of-frame orchestration.
|
||||
///
|
||||
/// Rust owns callback ordering, output offset/capacity accounting, and
|
||||
/// pledged-size validation. The opaque callback context retains only the
|
||||
/// private CCtx-dependent continue and trace operations in C; Rust serializes
|
||||
/// the epilogue from explicit frame and checksum projections.
|
||||
/// pledged-size validation. The continue state is projected explicitly and
|
||||
/// the opaque callback context retains only the private trace operation in C;
|
||||
/// Rust serializes the epilogue from explicit frame and checksum projections.
|
||||
#[repr(C)]
|
||||
pub struct ZSTD_rust_compressEndState {
|
||||
callback_context: *mut c_void,
|
||||
compress_continue: CompressEndContinueFn,
|
||||
compress_continue_state: *const ZSTD_rust_compressContinueState,
|
||||
trace: CompressEndTraceFn,
|
||||
consumed_src_size: *const u64,
|
||||
pledged_src_size_plus_one: u64,
|
||||
@@ -1181,7 +1172,7 @@ pub struct ZSTD_rust_compressEndState {
|
||||
|
||||
const _: () = {
|
||||
assert!(offset_of!(ZSTD_rust_compressEndState, callback_context) == 0);
|
||||
assert!(offset_of!(ZSTD_rust_compressEndState, compress_continue) == size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_compressEndState, compress_continue_state) == size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_compressEndState, trace) == 2 * size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_compressEndState, consumed_src_size) == 3 * size_of::<usize>());
|
||||
assert!(
|
||||
@@ -1229,14 +1220,17 @@ unsafe fn compress_end_body_with(
|
||||
src: *const c_void,
|
||||
src_size: usize,
|
||||
) -> usize {
|
||||
if state.consumed_src_size.is_null() || state.stage.is_null() || state.checksum_state.is_null()
|
||||
if state.compress_continue_state.is_null()
|
||||
|| state.consumed_src_size.is_null()
|
||||
|| state.stage.is_null()
|
||||
|| state.checksum_state.is_null()
|
||||
{
|
||||
return ERROR(ZstdErrorCode::Generic);
|
||||
}
|
||||
|
||||
let c_size = unsafe {
|
||||
(state.compress_continue)(
|
||||
state.callback_context,
|
||||
ZSTD_rust_compressContinue(
|
||||
state.compress_continue_state,
|
||||
dst,
|
||||
dst_capacity,
|
||||
src,
|
||||
@@ -10155,6 +10149,16 @@ mod tests {
|
||||
continue_frame: c_uint,
|
||||
continue_last_frame_chunk: c_uint,
|
||||
stage: c_int,
|
||||
window: ZSTD_rust_windowUpdateState,
|
||||
force_non_contiguous: c_int,
|
||||
next_to_update: c_uint,
|
||||
window_projection: ZSTD_rust_compressContinueWindowProjection,
|
||||
frame_chunk_clamp_state: Option<ZSTD_rust_frameChunkClampState>,
|
||||
frame_chunk_prepare_state: Option<ZSTD_rust_frameChunkPrepareState>,
|
||||
frame_chunk_state: Option<ZSTD_rust_frameChunkState>,
|
||||
continue_state: Option<ZSTD_rust_compressContinueState>,
|
||||
is_first_block: c_int,
|
||||
produced_c_size: u64,
|
||||
}
|
||||
|
||||
static COMPRESS_END_TEST_CHECKSUM_STATE: XXH64_state_t = XXH64_state_t {
|
||||
@@ -10172,19 +10176,33 @@ mod tests {
|
||||
unsafe { &mut *context.cast::<CompressEndTestContext>() }
|
||||
}
|
||||
|
||||
unsafe extern "C" fn compress_end_test_continue(
|
||||
unsafe extern "C" fn compress_end_test_frame_prepare_overflow(
|
||||
_context: *mut c_void,
|
||||
_src: *const c_void,
|
||||
_block_size: usize,
|
||||
) {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn compress_end_test_frame_prepare_window(
|
||||
_context: *mut c_void,
|
||||
_src: *const c_void,
|
||||
_block_size: usize,
|
||||
_max_dist: c_uint,
|
||||
) {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn compress_end_test_frame_target(
|
||||
context: *mut c_void,
|
||||
_dst: *mut c_void,
|
||||
_dst_capacity: usize,
|
||||
_src: *const c_void,
|
||||
_src_size: usize,
|
||||
frame: c_uint,
|
||||
last_frame_chunk: c_uint,
|
||||
last_block: c_uint,
|
||||
) -> usize {
|
||||
let context = unsafe { compress_end_test_context(context) };
|
||||
context.events.push("continue");
|
||||
context.continue_frame = frame;
|
||||
context.continue_last_frame_chunk = last_frame_chunk;
|
||||
context.continue_frame = 1;
|
||||
context.continue_last_frame_chunk = last_block;
|
||||
context.continue_result
|
||||
}
|
||||
|
||||
@@ -10196,14 +10214,105 @@ mod tests {
|
||||
|
||||
fn compress_end_test_state(
|
||||
context: &mut CompressEndTestContext,
|
||||
consumed_src_size: &u64,
|
||||
consumed_src_size: &mut u64,
|
||||
pledged_src_size_plus_one: u64,
|
||||
content_size_flag: c_int,
|
||||
) -> ZSTD_rust_compressEndState {
|
||||
context.stage = 1;
|
||||
let base = WINDOW_INIT_SENTINEL.as_ptr().cast::<c_void>();
|
||||
context.stage = ZSTD_COMPRESSION_STAGE_ONGOING;
|
||||
context.window = ZSTD_rust_windowUpdateState {
|
||||
nextSrc: base,
|
||||
base,
|
||||
dictBase: base,
|
||||
dictLimit: ZSTD_WINDOW_START_INDEX,
|
||||
lowLimit: ZSTD_WINDOW_START_INDEX,
|
||||
};
|
||||
context.force_non_contiguous = 0;
|
||||
context.next_to_update = ZSTD_WINDOW_START_INDEX;
|
||||
context.is_first_block = 1;
|
||||
context.produced_c_size = 0;
|
||||
context.window_projection = ZSTD_rust_compressContinueWindowProjection {
|
||||
next_src: ptr::addr_of_mut!(context.window.nextSrc),
|
||||
base: ptr::addr_of_mut!(context.window.base),
|
||||
dict_base: ptr::addr_of_mut!(context.window.dictBase),
|
||||
dict_limit: ptr::addr_of_mut!(context.window.dictLimit),
|
||||
low_limit: ptr::addr_of_mut!(context.window.lowLimit),
|
||||
force_non_contiguous: ptr::addr_of_mut!(context.force_non_contiguous),
|
||||
next_to_update: ptr::addr_of_mut!(context.next_to_update),
|
||||
};
|
||||
let callback_context = (context as *mut CompressEndTestContext).cast();
|
||||
context.frame_chunk_clamp_state = Some(ZSTD_rust_frameChunkClampState {
|
||||
next_to_update: ptr::addr_of_mut!(context.next_to_update),
|
||||
low_limit: ptr::addr_of!(context.window.lowLimit),
|
||||
});
|
||||
let frame_chunk_clamp_state = context
|
||||
.frame_chunk_clamp_state
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |state| state as *const _);
|
||||
context.frame_chunk_prepare_state = Some(ZSTD_rust_frameChunkPrepareState {
|
||||
callback_context,
|
||||
max_dist: 64,
|
||||
correct_overflow: compress_end_test_frame_prepare_overflow,
|
||||
check_dict_validity: compress_end_test_frame_prepare_window,
|
||||
enforce_max_dist: compress_end_test_frame_prepare_window,
|
||||
clamp_state: frame_chunk_clamp_state,
|
||||
});
|
||||
let frame_chunk_prepare_state = context
|
||||
.frame_chunk_prepare_state
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |state| state as *const _);
|
||||
context.frame_chunk_state = Some(ZSTD_rust_frameChunkState {
|
||||
callback_context,
|
||||
tmp_workspace: ptr::null_mut(),
|
||||
checksum_state: ptr::null_mut(),
|
||||
is_first_block: ptr::addr_of_mut!(context.is_first_block),
|
||||
stage: ptr::addr_of_mut!(context.stage),
|
||||
tmp_wksp_size: 0,
|
||||
block_size_max: 1,
|
||||
savings: 0,
|
||||
pre_block_splitter_level: 1,
|
||||
strategy: ZSTD_FAST,
|
||||
use_target_c_block_size: 1,
|
||||
block_splitter_enabled: 0,
|
||||
checksum_flag: 0,
|
||||
ending_stage: ZSTD_COMPRESSION_STAGE_ENDING,
|
||||
prepare_state: frame_chunk_prepare_state,
|
||||
compress_target: compress_end_test_frame_target,
|
||||
compress_split: compress_end_test_frame_target,
|
||||
compress_internal: compress_end_test_frame_target,
|
||||
});
|
||||
let frame_chunk_state = context
|
||||
.frame_chunk_state
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |state| state as *const _);
|
||||
context.continue_state = Some(ZSTD_rust_compressContinueState {
|
||||
callback_context,
|
||||
window_state: &context.window_projection,
|
||||
ldm_window_state: ptr::null(),
|
||||
overflow_state: ptr::null(),
|
||||
frame_chunk_state,
|
||||
compress_block: compress_end_test_frame_target,
|
||||
stage: ptr::addr_of_mut!(context.stage),
|
||||
consumed_src_size: consumed_src_size as *mut u64,
|
||||
produced_c_size: ptr::addr_of_mut!(context.produced_c_size),
|
||||
pledged_src_size_plus_one,
|
||||
block_size_max: 1,
|
||||
check_block_size: 0,
|
||||
no_dict_id_flag: 0,
|
||||
checksum_flag: 0,
|
||||
content_size_flag: 0,
|
||||
format: 0,
|
||||
window_log: 20,
|
||||
dict_id: 0,
|
||||
ldm_enabled: 0,
|
||||
});
|
||||
let continue_state = context
|
||||
.continue_state
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |state| state as *const _);
|
||||
ZSTD_rust_compressEndState {
|
||||
callback_context: (context as *mut CompressEndTestContext).cast(),
|
||||
compress_continue: compress_end_test_continue,
|
||||
callback_context,
|
||||
compress_continue_state: continue_state,
|
||||
trace: compress_end_test_trace,
|
||||
consumed_src_size: consumed_src_size as *const u64,
|
||||
pledged_src_size_plus_one,
|
||||
@@ -10224,20 +10333,28 @@ mod tests {
|
||||
continue_result: 3,
|
||||
..CompressEndTestContext::default()
|
||||
};
|
||||
let consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &consumed_src_size, 8, 1);
|
||||
let mut consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &mut consumed_src_size, 9, 1);
|
||||
let source = [0u8; 1];
|
||||
|
||||
let result = unsafe {
|
||||
ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0)
|
||||
ZSTD_rust_compressEnd(
|
||||
&state,
|
||||
dst.as_mut_ptr().cast(),
|
||||
dst.len(),
|
||||
source.as_ptr().cast(),
|
||||
source.len(),
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(result, 16);
|
||||
assert_eq!(result, 7);
|
||||
assert_eq!(context.events, ["continue", "trace"]);
|
||||
assert_eq!(
|
||||
(context.continue_frame, context.continue_last_frame_chunk),
|
||||
(1, 1)
|
||||
);
|
||||
assert_eq!(context.trace_extra, 13);
|
||||
assert_eq!(context.trace_extra, 4);
|
||||
assert_eq!((consumed_src_size, context.produced_c_size), (8, 3));
|
||||
assert_eq!(context.stage, 0);
|
||||
}
|
||||
|
||||
@@ -10248,11 +10365,18 @@ mod tests {
|
||||
continue_result: ERROR(ZstdErrorCode::MemoryAllocation),
|
||||
..CompressEndTestContext::default()
|
||||
};
|
||||
let consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &consumed_src_size, 8, 0);
|
||||
let mut consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &mut consumed_src_size, 8, 0);
|
||||
let source = [0u8; 1];
|
||||
|
||||
let result = unsafe {
|
||||
ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0)
|
||||
ZSTD_rust_compressEnd(
|
||||
&state,
|
||||
dst.as_mut_ptr().cast(),
|
||||
dst.len(),
|
||||
source.as_ptr().cast(),
|
||||
source.len(),
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(result, ERROR(ZstdErrorCode::MemoryAllocation));
|
||||
@@ -10261,16 +10385,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn compress_end_stops_before_validation_and_trace_when_epilogue_fails() {
|
||||
let mut dst = [0u8; 8];
|
||||
let mut dst = [0u8; 6];
|
||||
let mut context = CompressEndTestContext {
|
||||
continue_result: 3,
|
||||
..CompressEndTestContext::default()
|
||||
};
|
||||
let consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &consumed_src_size, 99, 1);
|
||||
let mut consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &mut consumed_src_size, 99, 1);
|
||||
let source = [0u8; 1];
|
||||
|
||||
let result = unsafe {
|
||||
ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0)
|
||||
ZSTD_rust_compressEnd(
|
||||
&state,
|
||||
dst.as_mut_ptr().cast(),
|
||||
dst.len(),
|
||||
source.as_ptr().cast(),
|
||||
source.len(),
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(result, ERROR(ZstdErrorCode::DstSizeTooSmall));
|
||||
@@ -10284,11 +10415,18 @@ mod tests {
|
||||
continue_result: 3,
|
||||
..CompressEndTestContext::default()
|
||||
};
|
||||
let consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &consumed_src_size, 99, 1);
|
||||
let mut consumed_src_size = 7;
|
||||
let state = compress_end_test_state(&mut context, &mut consumed_src_size, 99, 1);
|
||||
let source = [0u8; 1];
|
||||
|
||||
let result = unsafe {
|
||||
ZSTD_rust_compressEnd(&state, dst.as_mut_ptr().cast(), dst.len(), ptr::null(), 0)
|
||||
ZSTD_rust_compressEnd(
|
||||
&state,
|
||||
dst.as_mut_ptr().cast(),
|
||||
dst.len(),
|
||||
source.as_ptr().cast(),
|
||||
source.len(),
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(result, ERROR(ZstdErrorCode::SrcSizeWrong));
|
||||
|
||||
Reference in New Issue
Block a user