/* * Decoder orchestration is implemented in rust/src/zstd_decompress.rs. * * `ZSTD_DCtx_s` is intentionally still allocated and laid out by C: its * 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 leaves. Weak trace-symbol * discovery also stays here; Rust receives only a narrow trace projection. */ #define ZSTD_STATIC_LINKING_ONLY #include "../common/zstd_deps.h" #include "../common/error_private.h" #include "../common/mem.h" #include "../common/zstd_internal.h" #include "zstd_decompress_internal.h" #include "zstd_ddict.h" /* Keep the three public build-time tuning knobs in the C configuration domain. * Rust receives them through the small scalar-policy leaves below rather than * baking a second set of defaults into its source. */ #ifndef ZSTD_HEAPMODE # define ZSTD_HEAPMODE 1 #endif #ifndef ZSTD_MAXWINDOWSIZE_DEFAULT # define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1) #endif #ifndef ZSTD_NO_FORWARD_PROGRESS_MAX # define ZSTD_NO_FORWARD_PROGRESS_MAX 16 #endif /* Keep this in lock-step with ZSTD_rustDctxView in zstd_decompress.rs. * Every pointer that names a scalar is the address of that scalar; array and * embedded-object entries name their first byte. */ typedef struct { void* dctx; void* llt_ptr; void* mlt_ptr; void* oft_ptr; void* huf_ptr; void* entropy; void* workspace; size_t workspace_size; void* previous_dst_end; void* prefix_start; void* virtual_start; void* dict_end; void* expected; void* f_params; void* processed_c_size; void* decoded_size; void* b_type; void* stage; void* lit_entropy; void* fse_entropy; void* xxh_state; void* header_size; void* format; void* force_ignore_checksum; void* validate_checksum; void* lit_ptr; void* custom_mem; void* lit_size; void* rle_size; void* static_size; void* is_frame_decompression; void* ddict_local; void* ddict; void* dict_id; void* ddict_is_cold; void* dict_uses; void* ddict_set; void* ref_multiple_ddicts; void* disable_huf_asm; void* max_block_size_param; void* stream_stage; void* in_buff; void* in_buff_size; void* in_pos; void* max_window_size; void* out_buff; void* out_buff_size; void* out_start; void* out_end; void* lh_size; void* legacy_context; void* previous_legacy_version; void* legacy_version; void* hostage_byte; void* no_forward_progress; void* out_buffer_mode; void* expected_out_buffer; void* lit_buffer; void* lit_buffer_end; void* lit_buffer_location; void* lit_extra_buffer; size_t lit_extra_buffer_size; void* header_buffer; size_t header_buffer_size; void* oversized_duration; void* fuzz_begin; void* fuzz_end; size_t dctx_size; } ZSTD_rustDctxView; typedef char ZSTD_rust_dctx_view_layout[ (offsetof(ZSTD_rustDctxView, dctx) == 0 && offsetof(ZSTD_rustDctxView, static_size) == 29 * sizeof(void*) && offsetof(ZSTD_rustDctxView, dctx_size) == 67 * sizeof(void*) && sizeof(ZSTD_rustDctxView) == 68 * sizeof(void*)) ? 1 : -1]; /* Rust exposes this as u64. Use the trace API's exact unsigned-long-long * representation instead of U64, whose typedef may be a different C type on * some targets even when it has the same width. */ typedef unsigned long long ZSTD_rustTraceCtx; #if ZSTD_TRACE typedef ZSTD_rustTraceCtx (*ZSTD_rustTraceBeginFn)(const ZSTD_DCtx* dctx); typedef void (*ZSTD_rustTraceEndFn)(ZSTD_rustTraceCtx traceCtx, const ZSTD_Trace* trace); #else typedef ZSTD_rustTraceCtx (*ZSTD_rustTraceBeginFn)(const void* dctx); typedef void (*ZSTD_rustTraceEndFn)(ZSTD_rustTraceCtx traceCtx, const void* trace); #endif typedef struct { ZSTD_rustTraceCtx* trace_ctx; ZSTD_rustTraceBeginFn begin; ZSTD_rustTraceEndFn end; const ZSTD_DCtx* 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_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); 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); typedef struct { size_t configured_max_window_size; } ZSTD_rustDefaultMaxWindowProjection; typedef char ZSTD_rust_default_max_window_projection_layout[ (offsetof(ZSTD_rustDefaultMaxWindowProjection, configured_max_window_size) == 0 && sizeof(ZSTD_rustDefaultMaxWindowProjection) == sizeof(size_t)) ? 1 : -1]; size_t ZSTD_rust_default_max_window_policy( const ZSTD_rustDefaultMaxWindowProjection* projection); typedef struct { int configured_max; } ZSTD_rustNoForwardProgressProjection; typedef char ZSTD_rust_no_forward_progress_projection_layout[ (offsetof(ZSTD_rustNoForwardProgressProjection, configured_max) == 0 && sizeof(ZSTD_rustNoForwardProgressProjection) == sizeof(int)) ? 1 : -1]; int ZSTD_rust_no_forward_progress_policy( const ZSTD_rustNoForwardProgressProjection* projection); typedef struct { int configured_mode; } ZSTD_rustHeapModeProjection; typedef char ZSTD_rust_heapmode_projection_layout[ (offsetof(ZSTD_rustHeapModeProjection, configured_mode) == 0 && sizeof(ZSTD_rustHeapModeProjection) == sizeof(int)) ? 1 : -1]; int ZSTD_rust_heapmode_policy(const ZSTD_rustHeapModeProjection* projection); typedef struct { unsigned configured_level; } ZSTD_rustLegacySupportProjection; typedef char ZSTD_rust_legacy_support_projection_layout[ (offsetof(ZSTD_rustLegacySupportProjection, configured_level) == 0 && sizeof(ZSTD_rustLegacySupportProjection) == sizeof(unsigned)) ? 1 : -1]; unsigned ZSTD_rust_legacy_support_policy( const ZSTD_rustLegacySupportProjection* projection); unsigned ZSTD_rust_legacy_support(void); void ZSTD_rust_dctx_view(ZSTD_DCtx* dctx, ZSTD_rustDctxView* out) { ZSTD_memset(out, 0, sizeof(*out)); if (dctx == NULL) return; out->dctx = dctx; out->llt_ptr = &dctx->LLTptr; out->mlt_ptr = &dctx->MLTptr; out->oft_ptr = &dctx->OFTptr; out->huf_ptr = &dctx->HUFptr; out->entropy = &dctx->entropy; out->workspace = dctx->workspace; out->workspace_size = sizeof(dctx->workspace); out->previous_dst_end = &dctx->previousDstEnd; out->prefix_start = &dctx->prefixStart; out->virtual_start = &dctx->virtualStart; out->dict_end = &dctx->dictEnd; out->expected = &dctx->expected; out->f_params = &dctx->fParams; out->processed_c_size = &dctx->processedCSize; out->decoded_size = &dctx->decodedSize; out->b_type = &dctx->bType; out->stage = &dctx->stage; out->lit_entropy = &dctx->litEntropy; out->fse_entropy = &dctx->fseEntropy; out->xxh_state = &dctx->xxhState; out->header_size = &dctx->headerSize; out->format = &dctx->format; out->force_ignore_checksum = &dctx->forceIgnoreChecksum; out->validate_checksum = &dctx->validateChecksum; out->lit_ptr = &dctx->litPtr; out->custom_mem = &dctx->customMem; out->lit_size = &dctx->litSize; out->rle_size = &dctx->rleSize; out->static_size = &dctx->staticSize; out->is_frame_decompression = &dctx->isFrameDecompression; out->ddict_local = &dctx->ddictLocal; out->ddict = &dctx->ddict; out->dict_id = &dctx->dictID; out->ddict_is_cold = &dctx->ddictIsCold; out->dict_uses = &dctx->dictUses; out->ddict_set = &dctx->ddictSet; out->ref_multiple_ddicts = &dctx->refMultipleDDicts; out->disable_huf_asm = &dctx->disableHufAsm; out->max_block_size_param = &dctx->maxBlockSizeParam; out->stream_stage = &dctx->streamStage; out->in_buff = &dctx->inBuff; out->in_buff_size = &dctx->inBuffSize; out->in_pos = &dctx->inPos; out->max_window_size = &dctx->maxWindowSize; out->out_buff = &dctx->outBuff; out->out_buff_size = &dctx->outBuffSize; out->out_start = &dctx->outStart; out->out_end = &dctx->outEnd; out->lh_size = &dctx->lhSize; #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) out->legacy_context = &dctx->legacyContext; out->previous_legacy_version = &dctx->previousLegacyVersion; out->legacy_version = &dctx->legacyVersion; #endif out->hostage_byte = &dctx->hostageByte; out->no_forward_progress = &dctx->noForwardProgress; out->out_buffer_mode = &dctx->outBufferMode; out->expected_out_buffer = &dctx->expectedOutBuffer; out->lit_buffer = &dctx->litBuffer; out->lit_buffer_end = &dctx->litBufferEnd; out->lit_buffer_location = &dctx->litBufferLocation; out->lit_extra_buffer = dctx->litExtraBuffer; out->lit_extra_buffer_size = sizeof(dctx->litExtraBuffer); out->header_buffer = dctx->headerBuffer; out->header_buffer_size = sizeof(dctx->headerBuffer); out->oversized_duration = &dctx->oversizedDuration; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION out->fuzz_begin = &dctx->dictContentBeginForFuzzing; out->fuzz_end = &dctx->dictContentEndForFuzzing; #endif out->dctx_size = sizeof(*dctx); } size_t ZSTD_rust_dctx_sizeof(void) { return sizeof(ZSTD_DCtx); } void ZSTD_dctx_init_platform(ZSTD_DCtx* dctx) { #if DYNAMIC_BMI2 ZSTD_rust_dctx_init_platform(&dctx->bmi2, DYNAMIC_BMI2); #else (void)dctx; ZSTD_rust_dctx_init_platform(NULL, DYNAMIC_BMI2); #endif } size_t ZSTD_rust_dctx_default_max_window_size(void) { ZSTD_rustDefaultMaxWindowProjection const projection = { ZSTD_MAXWINDOWSIZE_DEFAULT }; return ZSTD_rust_default_max_window_policy(&projection); } int ZSTD_rust_no_forward_progress_max(void) { ZSTD_rustNoForwardProgressProjection const projection = { ZSTD_NO_FORWARD_PROGRESS_MAX }; return ZSTD_rust_no_forward_progress_policy(&projection); } int ZSTD_rust_heapmode(void) { ZSTD_rustHeapModeProjection const projection = { ZSTD_HEAPMODE }; return ZSTD_rust_heapmode_policy(&projection); } size_t ZSTD_rust_decompress_stack(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { ZSTD_DCtx dctx; ZSTD_rustDecompressStackProjection const projection = { ZSTD_rust_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, ZSTD_rustDctxTraceView* out) { ZSTD_memset(out, 0, sizeof(*out)); out->dctx = dctx; #if ZSTD_TRACE out->trace_ctx = &dctx->traceCtx; out->begin = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin : NULL; out->end = (ZSTD_trace_decompress_end != NULL) ? ZSTD_trace_decompress_end : NULL; out->ddict = dctx->ddict; out->dictionary_is_cold = dctx->ddictIsCold; #endif } /* The Rust dispatcher has all version-specific legacy implementations. Keep * the active C configuration as a scalar leaf so test builds, which compile * every Rust legacy module but vary this C macro per target, retain the * historical support boundary. Rust owns normalization of that scalar. */ unsigned ZSTD_rust_legacy_support(void) { ZSTD_rustLegacySupportProjection const projection = { #if defined(ZSTD_LEGACY_SUPPORT) ZSTD_LEGACY_SUPPORT #else 0 #endif }; return ZSTD_rust_legacy_support_policy(&projection); }