feat(compress): move end-of-frame orchestration into Rust
Move ZSTD_compressEnd_public's continuation, epilogue placement, pledged-size validation, trace ordering, and output accounting into the Rust compression projection. Keep CCtx-dependent continuation, checksum/epilogue, and trace behavior behind opaque C callbacks with compile-time ABI layout checks. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml compress_end_ -- --test-threads=1 - ulimit -v 41943040; make -B -C lib -j1 lib - ulimit -v 41943040; make -B -C programs -j1 zstd - ulimit -v 41943040; make -B -C tests -j1 test-cli-tests
This commit is contained in:
@@ -232,6 +232,50 @@ typedef char ZSTD_rust_compress_continue_state_layout[
|
||||
== (sizeof(void*) == 8 ? 96 : 52))
|
||||
? 1 : -1];
|
||||
|
||||
/* Rust owns the end-of-frame orchestration. The callbacks retain the
|
||||
* private CCtx-dependent continue, epilogue, and trace operations in C. */
|
||||
typedef size_t (*ZSTD_rust_compressEndContinue_f)(void* context,
|
||||
void* dst,
|
||||
size_t dstCapacity,
|
||||
const void* src,
|
||||
size_t srcSize,
|
||||
U32 frame,
|
||||
U32 lastFrameChunk);
|
||||
typedef size_t (*ZSTD_rust_compressEndEpilogue_f)(void* context,
|
||||
void* dst,
|
||||
size_t dstCapacity);
|
||||
typedef void (*ZSTD_rust_compressEndTrace_f)(void* context,
|
||||
size_t extraCSize);
|
||||
typedef struct {
|
||||
void* callbackContext;
|
||||
ZSTD_rust_compressEndContinue_f compressContinue;
|
||||
ZSTD_rust_compressEndEpilogue_f writeEpilogue;
|
||||
ZSTD_rust_compressEndTrace_f trace;
|
||||
unsigned long long* consumedSrcSize;
|
||||
U64 pledgedSrcSizePlusOne;
|
||||
int contentSizeFlag;
|
||||
} ZSTD_rust_compressEndState;
|
||||
size_t ZSTD_rust_compressEnd(const ZSTD_rust_compressEndState* state,
|
||||
void* dst, size_t dstCapacity,
|
||||
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)
|
||||
== sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressEndState, writeEpilogue)
|
||||
== 2 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressEndState, trace)
|
||||
== 3 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressEndState, consumedSrcSize)
|
||||
== 4 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressEndState, pledgedSrcSizePlusOne)
|
||||
== 5 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_compressEndState, contentSizeFlag)
|
||||
== 5 * sizeof(void*) + sizeof(U64)
|
||||
&& sizeof(ZSTD_rust_compressEndState)
|
||||
== (sizeof(void*) == 8 ? 56 : 32))
|
||||
? 1 : -1];
|
||||
|
||||
/* Rust owns the single-threaded buffered/stable stream state machine. The
|
||||
* projection contains only stream bookkeeping and callback slots; operations
|
||||
* which still need the private CCtx layout remain C callbacks. */
|
||||
@@ -4045,31 +4089,42 @@ 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 size_t ZSTD_rust_compressEnd_writeEpilogue(
|
||||
void* context, void* dst, size_t dstCapacity)
|
||||
{
|
||||
return ZSTD_writeEpilogue((ZSTD_CCtx*)context, dst, dstCapacity);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_compressEnd_trace(void* context, size_t extraCSize)
|
||||
{
|
||||
ZSTD_CCtx_trace((ZSTD_CCtx*)context, extraCSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t endResult;
|
||||
size_t const cSize = ZSTD_compressContinue_dispatch(
|
||||
cctx, dst, dstCapacity, src, srcSize,
|
||||
1 /* frame mode */, 1 /* last chunk */,
|
||||
cctx->blockSizeMax, 0 /* block size already selected */);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue failed");
|
||||
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
||||
FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
|
||||
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
||||
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
|
||||
DEBUGLOG(4, "end of frame : controlling src size");
|
||||
RETURN_ERROR_IF(
|
||||
cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
|
||||
srcSize_wrong,
|
||||
"error : pledgedSrcSize = %u, while realSrcSize = %u",
|
||||
(unsigned)cctx->pledgedSrcSizePlusOne-1,
|
||||
(unsigned)cctx->consumedSrcSize);
|
||||
}
|
||||
ZSTD_CCtx_trace(cctx, endResult);
|
||||
return cSize + endResult;
|
||||
ZSTD_rust_compressEndState state;
|
||||
state.callbackContext = cctx;
|
||||
state.compressContinue = ZSTD_rust_compressEnd_continue;
|
||||
state.writeEpilogue = ZSTD_rust_compressEnd_writeEpilogue;
|
||||
state.trace = ZSTD_rust_compressEnd_trace;
|
||||
state.consumedSrcSize = &cctx->consumedSrcSize;
|
||||
state.pledgedSrcSizePlusOne = cctx->pledgedSrcSizePlusOne;
|
||||
state.contentSizeFlag = cctx->appliedParams.fParams.contentSizeFlag;
|
||||
return ZSTD_rust_compressEnd(
|
||||
&state, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
/* NOTE: Must just wrap ZSTD_compressEnd_public() */
|
||||
|
||||
Reference in New Issue
Block a user