feat(decompress): move trace-record policy into Rust

Keep weak-symbol lookup and the conditional traceCtx/DCtx layout in the C
adapter, but project only the trace slot, callback pointers, context pointer,
and dictionary metadata into Rust. Rust now decides begin/end eligibility and
builds the ABI-compatible trace record, preserving null callbacks, streaming
and size conversion semantics. Existing call sites remain in their
success-only branches, so checksum/error paths still emit no trace end.

Test Plan:
- rustfmt --edition 2021 --check rust/src/zstd_decompress.rs
- git diff --check and git diff --cached --check
- Static rg/diff inspection of weak callbacks, traceCtx lifecycle, dictionary
  metadata, and success-only trace-end call sites
- No cargo, make, native, fuzz, or heavy tests run by request
This commit is contained in:
2026-07-20 02:35:27 +02:00
parent 7af1b27140
commit e7568ae8bd
2 changed files with 317 additions and 52 deletions
+46 -36
View File
@@ -5,7 +5,8 @@
* optional members vary with the build configuration and the block decoder
* shares that object. This translation unit is therefore a deliberately
* narrow ABI adapter. It projects field addresses to Rust while retaining
* the private layout and configuration-bound legacy and trace leaves.
* the private layout and configuration-bound legacy leaves. Weak trace-symbol
* discovery also stays here; Rust receives only a narrow trace projection.
*/
#define ZSTD_STATIC_LINKING_ONLY
@@ -105,7 +106,23 @@ typedef struct {
size_t dctx_size;
} ZSTD_rustDctxView;
typedef U64 ZSTD_rustTraceCtx;
typedef ZSTD_rustTraceCtx (*ZSTD_rustTraceBeginFn)(const void* dctx);
typedef void (*ZSTD_rustTraceEndFn)(ZSTD_rustTraceCtx traceCtx,
const void* trace);
typedef struct {
ZSTD_rustTraceCtx* trace_ctx;
ZSTD_rustTraceBeginFn begin;
ZSTD_rustTraceEndFn end;
const void* dctx;
const void* ddict;
int dictionary_is_cold;
} ZSTD_rustDctxTraceView;
void ZSTD_rust_dctx_view(ZSTD_DCtx* dctx, ZSTD_rustDctxView* out);
void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,
ZSTD_rustDctxTraceView* out);
size_t ZSTD_rust_dctx_sizeof(void);
void ZSTD_rust_dctx_init_platform(ZSTD_DCtx* dctx);
size_t ZSTD_rust_dctx_default_max_window_size(void);
@@ -117,11 +134,25 @@ ZSTD_DDict* ZSTD_rust_create_ddict(const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
ZSTD_customMem customMem);
void ZSTD_rust_dctx_trace_begin(ZSTD_DCtx* dctx);
void ZSTD_rust_dctx_trace_end(ZSTD_DCtx* dctx, U64 uncompressedSize,
U64 compressedSize, int streaming);
unsigned ZSTD_rust_legacy_support(void);
#if ZSTD_TRACE
static ZSTD_rustTraceCtx ZSTD_rust_trace_begin_callback(const void* dctx)
{
return (ZSTD_trace_decompress_begin != NULL)
? ZSTD_trace_decompress_begin((const ZSTD_DCtx*)dctx) : 0;
}
static void ZSTD_rust_trace_end_callback(ZSTD_rustTraceCtx traceCtx,
const void* trace)
{
if (ZSTD_trace_decompress_end != NULL) {
ZSTD_trace_decompress_end((ZSTD_TraceCtx)traceCtx,
(const ZSTD_Trace*)trace);
}
}
#endif
void ZSTD_rust_dctx_view(ZSTD_DCtx* dctx, ZSTD_rustDctxView* out)
{
ZSTD_memset(out, 0, sizeof(*out));
@@ -260,40 +291,19 @@ ZSTD_DDict* ZSTD_rust_create_ddict(const void* dict, size_t dictSize,
dictContentType, customMem);
}
void ZSTD_rust_dctx_trace_begin(ZSTD_DCtx* dctx)
void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,
ZSTD_rustDctxTraceView* out)
{
ZSTD_memset(out, 0, sizeof(*out));
out->dctx = dctx;
#if ZSTD_TRACE
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL)
? ZSTD_trace_decompress_begin(dctx) : 0;
#else
(void)dctx;
#endif
}
void ZSTD_rust_dctx_trace_end(ZSTD_DCtx* dctx, U64 uncompressedSize,
U64 compressedSize, int streaming)
{
#if ZSTD_TRACE
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
ZSTD_Trace trace;
ZSTD_memset(&trace, 0, sizeof(trace));
trace.version = ZSTD_VERSION_NUMBER;
trace.streaming = streaming;
if (dctx->ddict) {
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
trace.dictionaryIsCold = dctx->ddictIsCold;
}
trace.uncompressedSize = (size_t)uncompressedSize;
trace.compressedSize = (size_t)compressedSize;
trace.dctx = dctx;
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
}
#else
(void)dctx;
(void)uncompressedSize;
(void)compressedSize;
(void)streaming;
out->trace_ctx = &dctx->traceCtx;
out->begin = (ZSTD_trace_decompress_begin != NULL)
? ZSTD_rust_trace_begin_callback : NULL;
out->end = (ZSTD_trace_decompress_end != NULL)
? ZSTD_rust_trace_end_callback : NULL;
out->ddict = dctx->ddict;
out->dictionary_is_cold = dctx->ddictIsCold;
#endif
}