refactor(compress): move sequence generation policy to Rust

ZSTD_generateSequences() previously mixed public parameter validation,
temporary-output allocation, sequence-collector setup, compression, and cleanup
inside the C translation unit. Move that ordering into Rust behind callbacks so
private ZSTD_CCtx and SeqCollector layouts remain C-owned. The adapter retains
C allocation, context access, and the existing ZSTD_compress2 operation, while
Rust guarantees temporary-output cleanup after collector setup failures and
compression errors and preserves the original target-block-size and worker
parameter checks.

Focused callback tests cover validation-before-allocation, cleanup on setup
failure, and successful callback ordering/count publication.

Test Plan:
- `cargo fmt --manifest-path rust/Cargo.toml --all -- --check` -- passed
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml generate_sequences --lib` -- passed (3 tests)
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets` -- passed (762 tests)
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings` -- passed
- `ulimit -v 41943040; make -j1` -- passed
This commit is contained in:
2026-07-20 04:30:33 +02:00
parent 53218c5537
commit 66e7799f04
2 changed files with 360 additions and 30 deletions
+95 -30
View File
@@ -5454,39 +5454,104 @@ static void ZSTD_initBuildSeqStoreState(
/* ZSTD_sequenceBound() lives in rust/src/zstd_compress_api.rs. */
typedef size_t (*ZSTD_rust_generateSequencesGetParameter_f)(
void* context, int param, int* value);
typedef void* (*ZSTD_rust_generateSequencesAllocate_f)(
void* context, size_t size);
typedef void (*ZSTD_rust_generateSequencesFree_f)(
void* context, void* pointer);
typedef size_t (*ZSTD_rust_generateSequencesSetCollector_f)(
void* context, ZSTD_Sequence* outSeqs, size_t outSeqsSize);
typedef size_t (*ZSTD_rust_generateSequencesCompress2_f)(
void* context, void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
typedef size_t (*ZSTD_rust_generateSequencesGetCount_f)(void* context);
typedef struct {
void* callbackContext;
ZSTD_rust_generateSequencesGetParameter_f getParameter;
ZSTD_rust_generateSequencesAllocate_f allocate;
ZSTD_rust_generateSequencesFree_f free;
ZSTD_rust_generateSequencesSetCollector_f setCollector;
ZSTD_rust_generateSequencesCompress2_f compress2;
ZSTD_rust_generateSequencesGetCount_f getCount;
} ZSTD_rust_generateSequencesState;
typedef char ZSTD_rust_generate_sequences_state_layout[
(offsetof(ZSTD_rust_generateSequencesState, callbackContext) == 0
&& offsetof(ZSTD_rust_generateSequencesState, getParameter)
== sizeof(void*)
&& offsetof(ZSTD_rust_generateSequencesState, allocate)
== 2 * sizeof(void*)
&& offsetof(ZSTD_rust_generateSequencesState, free)
== 3 * sizeof(void*)
&& offsetof(ZSTD_rust_generateSequencesState, setCollector)
== 4 * sizeof(void*)
&& offsetof(ZSTD_rust_generateSequencesState, compress2)
== 5 * sizeof(void*)
&& offsetof(ZSTD_rust_generateSequencesState, getCount)
== 6 * sizeof(void*)
&& sizeof(ZSTD_rust_generateSequencesState) == 7 * sizeof(void*))
? 1 : -1];
size_t ZSTD_rust_generateSequences(
const ZSTD_rust_generateSequencesState* state,
ZSTD_Sequence* outSeqs, size_t outSeqsSize,
const void* src, size_t srcSize);
static size_t ZSTD_rust_generateSequences_getParameter(
void* context, int param, int* value)
{
return ZSTD_CCtx_getParameter(
(const ZSTD_CCtx*)context, (ZSTD_cParameter)param, value);
}
static void* ZSTD_rust_generateSequences_allocate(void* context, size_t size)
{
(void)context;
return ZSTD_customMalloc(size, ZSTD_defaultCMem);
}
static void ZSTD_rust_generateSequences_free(void* context, void* pointer)
{
(void)context;
ZSTD_customFree(pointer, ZSTD_defaultCMem);
}
static size_t ZSTD_rust_generateSequences_setCollector(
void* context, ZSTD_Sequence* outSeqs, size_t outSeqsSize)
{
ZSTD_CCtx* const zc = (ZSTD_CCtx*)context;
zc->seqCollector.collectSequences = 1;
zc->seqCollector.seqStart = outSeqs;
zc->seqCollector.seqIndex = 0;
zc->seqCollector.maxSequences = outSeqsSize;
return 0;
}
static size_t ZSTD_rust_generateSequences_compress2(
void* context, void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
return ZSTD_compress2((ZSTD_CCtx*)context, dst, dstCapacity, src, srcSize);
}
static size_t ZSTD_rust_generateSequences_getCount(void* context)
{
return ((const ZSTD_CCtx*)context)->seqCollector.seqIndex;
}
size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
size_t outSeqsSize, const void* src, size_t srcSize)
{
const size_t dstCapacity = ZSTD_compressBound(srcSize);
void* dst; /* Make C90 happy. */
SeqCollector seqCollector;
{
int targetCBlockSize;
FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), "");
RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, "targetCBlockSize != 0");
}
{
int nbWorkers;
FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), "");
RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, "nbWorkers != 0");
}
dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
seqCollector.collectSequences = 1;
seqCollector.seqStart = outSeqs;
seqCollector.seqIndex = 0;
seqCollector.maxSequences = outSeqsSize;
zc->seqCollector = seqCollector;
{
const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
ZSTD_customFree(dst, ZSTD_defaultCMem);
FORWARD_IF_ERROR(ret, "ZSTD_compress2 failed");
}
assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize));
return zc->seqCollector.seqIndex;
ZSTD_rust_generateSequencesState const state = {
zc,
ZSTD_rust_generateSequences_getParameter,
ZSTD_rust_generateSequences_allocate,
ZSTD_rust_generateSequences_free,
ZSTD_rust_generateSequences_setCollector,
ZSTD_rust_generateSequences_compress2,
ZSTD_rust_generateSequences_getCount
};
return ZSTD_rust_generateSequences(
&state, outSeqs, outSeqsSize, src, srcSize);
}
/* ZSTD_mergeBlockDelimiters() lives in rust/src/zstd_compress_api.rs. */