refactor(compress): move MT stream loop policy to Rust
The multithreaded branch of `ZSTD_compressStream2_c` performed the complete post-call result classification in C: it prioritized errors, recognized a completed end directive, and applied different progress rules for continue, flush, and end operations. Those decisions were scalar policy around a C-owned MT call, but remained embedded beside private counters, reset, and tracing. Rust now classifies one projected iteration and returns an explicit action for continue, break, error, or completed end. The C shim still owns the MT call, input/output accounting, error forwarding, private context mutation, reset, and trace callback; the existing condition ordering and progress comparisons are preserved. ABI layout assertions and focused tests cover error precedence, completed end, progress-based continue termination, and pending/full output. Test Plan: - `git diff --cached --check` -- passed - `rustfmt --edition 2021 --check rust/src/zstd_compress.rs` -- passed - Full capped Rust/native verification is the next serial step.
This commit is contained in:
@@ -852,6 +852,44 @@ typedef char ZSTD_rust_compress_stream2_init_policy_state_layout[
|
||||
&& sizeof(ZSTD_rust_compressStream2InitPolicyState)
|
||||
== 2 * sizeof(int) + 7 * sizeof(size_t))
|
||||
? 1 : -1];
|
||||
typedef struct {
|
||||
int endOp;
|
||||
size_t flushMin;
|
||||
size_t inputPos;
|
||||
size_t inputSize;
|
||||
size_t inputPosBefore;
|
||||
size_t outputPos;
|
||||
size_t outputSize;
|
||||
size_t outputPosBefore;
|
||||
} ZSTD_rust_compressStream2MTLoopPolicyState;
|
||||
enum {
|
||||
ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_CONTINUE = 0,
|
||||
ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_BREAK = 1,
|
||||
ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_ERROR = 2,
|
||||
ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_END_COMPLETE = 3
|
||||
};
|
||||
int ZSTD_rust_compressStream2MTLoopPolicy(
|
||||
const ZSTD_rust_compressStream2MTLoopPolicyState* state);
|
||||
typedef char ZSTD_rust_compress_stream2_mt_loop_policy_state_layout[
|
||||
(offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, endOp) == 0
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, flushMin)
|
||||
== sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, inputPos)
|
||||
== 2 * sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, inputSize)
|
||||
== 3 * sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, inputPosBefore)
|
||||
== 4 * sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, outputPos)
|
||||
== 5 * sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState, outputSize)
|
||||
== 6 * sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_compressStream2MTLoopPolicyState,
|
||||
outputPosBefore)
|
||||
== 7 * sizeof(size_t)
|
||||
&& sizeof(ZSTD_rust_compressStream2MTLoopPolicyState)
|
||||
== 8 * sizeof(size_t))
|
||||
? 1 : -1];
|
||||
int ZSTD_rust_simpleCompress2Level(const void* cctx, size_t srcSize);
|
||||
typedef int (*ZSTD_rust_simpleCompress2Level_f)(const void* cctx, size_t srcSize);
|
||||
typedef struct {
|
||||
@@ -8458,27 +8496,27 @@ size_t ZSTD_compressStream2_c( ZSTD_CCtx* cctx,
|
||||
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
||||
cctx->consumedSrcSize += (U64)(input->pos - ipos);
|
||||
cctx->producedCSize += (U64)(output->pos - opos);
|
||||
if ( ZSTD_isError(flushMin)
|
||||
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
||||
if (flushMin == 0)
|
||||
ZSTD_CCtx_trace(cctx, 0);
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
||||
}
|
||||
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
||||
|
||||
if (endOp == ZSTD_e_continue) {
|
||||
/* We only require some progress with ZSTD_e_continue, not maximal progress.
|
||||
* We're done if we've consumed or produced any bytes, or either buffer is
|
||||
* full.
|
||||
*/
|
||||
if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size)
|
||||
break;
|
||||
} else {
|
||||
assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
|
||||
/* We require maximal progress. We're done when the flush is complete or the
|
||||
* output buffer is full.
|
||||
*/
|
||||
if (flushMin == 0 || output->pos == output->size)
|
||||
{ ZSTD_rust_compressStream2MTLoopPolicyState const state = {
|
||||
(int)endOp,
|
||||
flushMin,
|
||||
input->pos,
|
||||
input->size,
|
||||
ipos,
|
||||
output->pos,
|
||||
output->size,
|
||||
opos
|
||||
};
|
||||
int const loopPolicy =
|
||||
ZSTD_rust_compressStream2MTLoopPolicy(&state);
|
||||
if (loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_ERROR
|
||||
|| loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_END_COMPLETE) {
|
||||
if (loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_END_COMPLETE)
|
||||
ZSTD_CCtx_trace(cctx, 0);
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
||||
}
|
||||
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
||||
if (loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_BREAK
|
||||
|| loopPolicy == ZSTD_RUST_COMPRESS_STREAM2_MT_LOOP_POLICY_END_COMPLETE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user