Files
zstd-rs/lib/decompress/zstd_decompress_block.c
ddidderr e5eebd4892 feat(rust): port compressed block decoding
Move literal decoding, sequence-table construction, FSE sequence decoding, and
sequence execution into Rust. The C shim retains ownership of the configured
decoder context and passes only the leaf state needed by the block codec.

Correct the two high offset-code bases while porting the tables. Their prior
values made valid large-window streams decode as corrupted data; the new unit
test fixes the exact values and a native zstream regression exercises them.
High-level frame and streaming context control remains C for now.

Test Plan:
- cargo test --all-targets
- cargo test --target i686-unknown-linux-gnu --all-targets
- cargo clippy && cargo clippy --benches && cargo clippy --tests
- cargo +nightly fmt
- make -B -C tests -j2 fuzzer zstreamtest invalidDictionaries poolTests
- ./tests/fuzzer -s5346 -i1 --no-big-tests
- ./tests/zstreamtest -i3000 -s334462
- ./tests/invalidDictionaries
- timeout 20s stdbuf -oL ./tests/poolTests

Refs: rust/README.md
2026-07-11 08:07:40 +02:00

160 lines
5.9 KiB
C

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
/*
* Compressed-block decoding is implemented in
* rust/src/zstd_decompress_block.rs. Keep `ZSTD_DCtx` C-owned: it has
* optional build-dependent fields, while this small view contains only the
* leaves read or written by the Rust decoder. No decoder algorithm remains
* in this translation unit.
*/
#include "../common/zstd_deps.h"
#include "../common/zstd_internal.h"
#include "zstd_decompress_internal.h"
#include "zstd_decompress_block.h"
typedef char ZSTD_rust_block_seq_symbol_layout[(sizeof(ZSTD_seqSymbol) == 8) ? 1 : -1];
typedef char ZSTD_rust_block_entropy_rep_offset[
(offsetof(ZSTD_entropyDTables_t, rep) == 26652) ? 1 : -1];
typedef char ZSTD_rust_block_entropy_workspace_offset[
(offsetof(ZSTD_entropyDTables_t, workspace) == 26664) ? 1 : -1];
typedef struct {
const ZSTD_seqSymbol** lltPtr;
const ZSTD_seqSymbol** mltPtr;
const ZSTD_seqSymbol** oftPtr;
const HUF_DTable** hufPtr;
ZSTD_entropyDTables_t* entropy;
U32* workspace;
size_t workspaceSize;
const void** previousDstEnd;
const void** prefixStart;
const void** virtualStart;
const void** dictEnd;
size_t blockSizeMax;
int* isFrameDecompression;
U32* litEntropy;
U32* fseEntropy;
int bmi2;
int* ddictIsCold;
int disableHufAsm;
const BYTE** litPtr;
size_t* litSize;
size_t* rleSize;
BYTE** litBuffer;
const BYTE** litBufferEnd;
ZSTD_litLocation_e* litBufferLocation;
BYTE* litExtraBuffer;
size_t litExtraBufferSize;
} ZSTD_rustBlockCtx;
static ZSTD_rustBlockCtx ZSTD_rust_block_context(ZSTD_DCtx* dctx)
{
ZSTD_rustBlockCtx ctx;
ctx.lltPtr = &dctx->LLTptr;
ctx.mltPtr = &dctx->MLTptr;
ctx.oftPtr = &dctx->OFTptr;
ctx.hufPtr = &dctx->HUFptr;
ctx.entropy = &dctx->entropy;
ctx.workspace = dctx->workspace;
ctx.workspaceSize = sizeof(dctx->workspace);
ctx.previousDstEnd = &dctx->previousDstEnd;
ctx.prefixStart = &dctx->prefixStart;
ctx.virtualStart = &dctx->virtualStart;
ctx.dictEnd = &dctx->dictEnd;
ctx.blockSizeMax = dctx->fParams.blockSizeMax;
ctx.isFrameDecompression = &dctx->isFrameDecompression;
ctx.litEntropy = &dctx->litEntropy;
ctx.fseEntropy = &dctx->fseEntropy;
ctx.bmi2 = ZSTD_DCtx_get_bmi2(dctx);
ctx.ddictIsCold = &dctx->ddictIsCold;
ctx.disableHufAsm = dctx->disableHufAsm;
ctx.litPtr = &dctx->litPtr;
ctx.litSize = &dctx->litSize;
ctx.rleSize = &dctx->rleSize;
ctx.litBuffer = &dctx->litBuffer;
ctx.litBufferEnd = &dctx->litBufferEnd;
ctx.litBufferLocation = &dctx->litBufferLocation;
ctx.litExtraBuffer = dctx->litExtraBuffer;
ctx.litExtraBufferSize = ZSTD_LITBUFFEREXTRASIZE;
return ctx;
}
size_t ZSTD_rust_decodeLiteralsBlock_wrapper(
ZSTD_rustBlockCtx* ctx,
const void* src, size_t srcSize,
void* dst, size_t dstCapacity);
size_t ZSTD_rust_decodeSeqHeaders(
ZSTD_rustBlockCtx* ctx, int* nbSeqPtr,
const void* src, size_t srcSize);
size_t ZSTD_rust_decompressBlock_internal(
ZSTD_rustBlockCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize, int streaming);
void ZSTD_rust_checkContinuity(
ZSTD_rustBlockCtx* ctx, const void* dst, size_t dstSize);
size_t ZSTD_rust_decompressBlock_deprecated(
ZSTD_rustBlockCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
/* Hidden declaration for fullbench. */
size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,
const void* src, size_t srcSize,
void* dst, size_t dstCapacity);
size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,
const void* src, size_t srcSize,
void* dst, size_t dstCapacity)
{
ZSTD_rustBlockCtx ctx = ZSTD_rust_block_context(dctx);
return ZSTD_rust_decodeLiteralsBlock_wrapper(
&ctx, src, srcSize, dst, dstCapacity);
}
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
const void* src, size_t srcSize)
{
ZSTD_rustBlockCtx ctx = ZSTD_rust_block_context(dctx);
return ZSTD_rust_decodeSeqHeaders(&ctx, nbSeqPtr, src, srcSize);
}
size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const streaming_operation streaming)
{
ZSTD_rustBlockCtx ctx = ZSTD_rust_block_context(dctx);
return ZSTD_rust_decompressBlock_internal(&ctx, dst, dstCapacity, src, srcSize,
(int)streaming);
}
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)
{
ZSTD_rustBlockCtx ctx = ZSTD_rust_block_context(dctx);
ZSTD_rust_checkContinuity(&ctx, dst, dstSize);
}
size_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
ZSTD_rustBlockCtx ctx = ZSTD_rust_block_context(dctx);
return ZSTD_rust_decompressBlock_deprecated(&ctx,
dst, dstCapacity, src, srcSize);
}
/* NOTE: Must just wrap ZSTD_decompressBlock_deprecated(). */
size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
return ZSTD_decompressBlock_deprecated(dctx, dst, dstCapacity, src, srcSize);
}