fix(compress): preserve post-init MT stream dispatch

Transparent stream initialization can resolve an unknown source size to the
multithreaded path and update appliedParams.nbWorkers. The Rust stream2
fallback previously captured that value before initialization, then entered the
serial generic adapter while the context stage was still created. Unknown-size
stdin compression consequently returned StageWrong instead of producing a
frame.

Keep the worker-mode projection live through initialization so Rust observes
the applied value at the existing MT-versus-serial decision point. The ABI
layout assertions now cover the pointer projection, and a focused regression
test verifies that an initialization callback which selects MT dispatches the
MT step and preserves the expected callback order.

Test Plan:
- capped cargo +nightly fmt for the Rust workspace -- passed
- capped root and CLI cargo clippy with -D warnings -- passed
- capped serial make -j1 for single-threaded library, MT library, and CLI -- passed without the prior pointer-sign warning
- capped stdin compression/decompression round trip for unknown-size input -- passed
- capped original suite, including CLI tests, native tests, fuzzer, and both zstream phases -- passed; the final signedness-only ABI spelling cleanup was followed by a clean capped rebuild
- targeted root cargo test attempted but remains blocked at link time by pre-existing decompression bridge symbols (ZSTD_rust_dctx_trace_view, ZSTD_rust_dctx_view, and ZSTD_rust_block_context_init)
This commit is contained in:
2026-07-21 13:37:58 +02:00
parent b394cae70f
commit 7d7b18d60a
2 changed files with 101 additions and 27 deletions
+7 -9
View File
@@ -1064,7 +1064,8 @@ typedef struct {
int inBufferMode;
int outBufferMode;
int format;
int nbWorkers;
/* Transparent init may resolve a different worker mode for unknown sizes. */
const int* nbWorkers;
} ZSTD_rust_compressStream2Fields;
typedef struct {
ZSTD_rust_compressStream2Init_f initCompressStream2;
@@ -1112,10 +1113,11 @@ typedef char ZSTD_rust_compress_stream2_fields_layout[
&& offsetof(ZSTD_rust_compressStream2Fields, format)
== 10 * sizeof(void*) + sizeof(unsigned long long) + 2 * sizeof(int)
&& offsetof(ZSTD_rust_compressStream2Fields, nbWorkers)
== 10 * sizeof(void*) + sizeof(unsigned long long) + 3 * sizeof(int)
== ((10 * sizeof(void*) + sizeof(unsigned long long) + 3 * sizeof(int)
+ sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*)
&& sizeof(ZSTD_rust_compressStream2Fields)
== ((10 * sizeof(void*) + sizeof(unsigned long long) + 4 * sizeof(int)
+ sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*))
== offsetof(ZSTD_rust_compressStream2Fields, nbWorkers)
+ sizeof(const int*))
? 1 : -1];
typedef char ZSTD_rust_compress_stream2_callbacks_layout[
(offsetof(ZSTD_rust_compressStream2Callbacks, initCompressStream2) == 0
@@ -8922,11 +8924,7 @@ size_t ZSTD_compressStream2_c( ZSTD_CCtx* cctx,
(int)cctx->requestedParams.inBufferMode,
(int)cctx->requestedParams.outBufferMode,
(int)cctx->requestedParams.format,
#ifdef ZSTD_MULTITHREAD
(int)cctx->appliedParams.nbWorkers,
#else
0,
#endif
&cctx->appliedParams.nbWorkers,
};
ZSTD_rust_compressStream2Callbacks const callbacks = {
ZSTD_rust_compressStream2_init,