refactor(decompress): move stack entry policy to Rust

The stack-backed one-shot decompression entry point used to make its own
heap-mode rejection, static DCtx initialization, allocation-error mapping,
and dispatch ordering in C. That kept scalar control flow beside the private
DCtx layout even though Rust already owns the decompression policy and context
leaf.

Rust now consumes an ABI-checked scalar projection and callback set. It makes
the branch and ordering decisions, maps a failed static initializer to the
same memory-allocation error, and invokes the existing C-owned context leaf.
The C shim retains the local stack object, private DCtx layout, and
`ZSTD_initStaticDCtx` implementation. Recording-callback tests cover heap
rejection, initializer failure, and successful initialization-to-dispatch
ordering without fabricating the private context layout.

Test Plan:
- `git diff --cached --check` -- passed
- `rustfmt --edition 2021 --check rust/src/zstd_decompress.rs` -- passed
- Full capped Rust/native verification remains pending until the parallel
  compression seam is integrated.
This commit is contained in:
2026-07-21 06:52:40 +02:00
parent bc3c3b1ac6
commit 35150c3cff
2 changed files with 321 additions and 9 deletions
+59 -9
View File
@@ -137,13 +137,56 @@ void ZSTD_dctx_init_platform(ZSTD_DCtx* dctx);
void ZSTD_rust_dctx_init_platform(void* bmi2, int dynamic_bmi2);
size_t ZSTD_rust_dctx_default_max_window_size(void);
int ZSTD_rust_no_forward_progress_max(void);
int ZSTD_rust_heapmode(void);
int ZSTD_rust_decompress_stack_uses_heap(int heapmode);
size_t ZSTD_rust_decompress_stack(void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
size_t ZSTD_rust_decompress_stack_context(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
typedef struct {
int heapmode;
void* workspace;
size_t workspace_size;
void* dst;
size_t dst_capacity;
const void* src;
size_t src_size;
} ZSTD_rustDecompressStackProjection;
typedef char ZSTD_rust_decompress_stack_projection_layout[
(offsetof(ZSTD_rustDecompressStackProjection, heapmode) == 0
&& offsetof(ZSTD_rustDecompressStackProjection, workspace) == sizeof(void*)
&& offsetof(ZSTD_rustDecompressStackProjection, workspace_size)
== 2 * sizeof(void*)
&& offsetof(ZSTD_rustDecompressStackProjection, dst)
== 3 * sizeof(void*)
&& offsetof(ZSTD_rustDecompressStackProjection, dst_capacity)
== 4 * sizeof(void*)
&& offsetof(ZSTD_rustDecompressStackProjection, src)
== 5 * sizeof(void*)
&& offsetof(ZSTD_rustDecompressStackProjection, src_size)
== 6 * sizeof(void*)
&& sizeof(ZSTD_rustDecompressStackProjection) == 7 * sizeof(void*))
? 1 : -1];
typedef ZSTD_DCtx* (*ZSTD_rustInitStaticDCtxFn)(void* workspace,
size_t workspace_size);
typedef size_t (*ZSTD_rustDecompressStackContextFn)(
ZSTD_DCtx* dctx, void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
typedef struct {
ZSTD_rustInitStaticDCtxFn init_static_dctx;
ZSTD_rustDecompressStackContextFn decompress_context;
} ZSTD_rustDecompressStackCallbacks;
typedef char ZSTD_rust_decompress_stack_callbacks_layout[
(offsetof(ZSTD_rustDecompressStackCallbacks, init_static_dctx) == 0
&& offsetof(ZSTD_rustDecompressStackCallbacks, decompress_context)
== sizeof(void*)
&& sizeof(ZSTD_rustDecompressStackCallbacks) == 2 * sizeof(void*))
? 1 : -1];
size_t ZSTD_rust_decompress_stack_action(
const ZSTD_rustDecompressStackProjection* projection,
const ZSTD_rustDecompressStackCallbacks* callbacks);
unsigned ZSTD_rust_legacy_support(void);
#if ZSTD_TRACE
@@ -275,14 +318,21 @@ int ZSTD_rust_heapmode(void)
size_t ZSTD_rust_decompress_stack(void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
if (ZSTD_rust_decompress_stack_uses_heap(ZSTD_HEAPMODE)) {
return ERROR(GENERIC);
}
ZSTD_DCtx dctx;
ZSTD_DCtx* const initialized = ZSTD_initStaticDCtx(&dctx, sizeof(dctx));
if (initialized == NULL) return ERROR(memory_allocation);
return ZSTD_rust_decompress_stack_context(initialized, dst, dstCapacity,
src, srcSize);
ZSTD_rustDecompressStackProjection const projection = {
ZSTD_HEAPMODE,
&dctx,
sizeof(dctx),
dst,
dstCapacity,
src,
srcSize
};
ZSTD_rustDecompressStackCallbacks const callbacks = {
ZSTD_initStaticDCtx,
ZSTD_rust_decompress_stack_context
};
return ZSTD_rust_decompress_stack_action(&projection, &callbacks);
}
void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,