feat(compress): move compress2 fallback orchestration into Rust

Move the stable-buffer fallback behind ZSTD_compress2() into a Rust-owned
projection. Rust now owns reset/mode-switch/stream-end ordering and maps
remaining output to dstSize_tooSmall, while C retains the private CCtx reset,
mode mutation, and simple-arguments stream adapter callbacks.

Test Plan:
- cargo +nightly fmt --manifest-path rust/Cargo.toml
- cargo test --manifest-path rust/Cargo.toml compress2_fallback -- --test-threads=1 (2 passed)
- cargo clippy --manifest-path rust/Cargo.toml --lib -- -D warnings
- cargo clippy --manifest-path rust/Cargo.toml --tests -- -D warnings
- make -B -C lib -j1 lib
- make -B -C programs -j1 zstd
- all commands used CARGO_BUILD_JOBS=1 where applicable and
  ulimit -v 41943040; no heavyweight jobs ran concurrently

Commit is intentionally unsigned because GPG pinentry hangs in this
non-interactive environment.
This commit is contained in:
2026-07-19 10:30:25 +02:00
parent 11120fd70c
commit 17cfedd56e
2 changed files with 299 additions and 24 deletions
+61 -24
View File
@@ -61,6 +61,37 @@ size_t ZSTD_rust_prepareCCtxForSimpleCompression(void* cctx,
int ZSTD_rust_compressCCtxStrategy(size_t srcSize, int compressionLevel);
size_t ZSTD_rust_resetCCtxForSimpleCompressionSession(void* cctx);
void ZSTD_rust_markSimpleCompression2Complete(void* cctx);
typedef size_t (*ZSTD_rust_compress2Reset_f)(void* context);
typedef void (*ZSTD_rust_compress2SetBufferModes_f)(
void* context, int inBufferMode, int outBufferMode);
typedef size_t (*ZSTD_rust_compress2StreamEnd_f)(
void* context, void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos);
typedef struct {
void* callbackContext;
ZSTD_rust_compress2Reset_f resetSession;
ZSTD_rust_compress2SetBufferModes_f setBufferModes;
ZSTD_rust_compress2StreamEnd_f compressStreamEnd;
int originalInBufferMode;
int originalOutBufferMode;
} ZSTD_rust_compress2State;
size_t ZSTD_rust_compress2(const ZSTD_rust_compress2State* state,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
typedef char ZSTD_rust_compress2_state_layout[
(offsetof(ZSTD_rust_compress2State, callbackContext) == 0
&& offsetof(ZSTD_rust_compress2State, resetSession) == sizeof(void*)
&& offsetof(ZSTD_rust_compress2State, setBufferModes)
== 2 * sizeof(void*)
&& offsetof(ZSTD_rust_compress2State, compressStreamEnd)
== 3 * sizeof(void*)
&& offsetof(ZSTD_rust_compress2State, originalInBufferMode)
== 4 * sizeof(void*)
&& offsetof(ZSTD_rust_compress2State, originalOutBufferMode)
== 4 * sizeof(void*) + sizeof(int)
&& sizeof(ZSTD_rust_compress2State)
== 4 * sizeof(void*) + 2 * sizeof(int))
? 1 : -1];
size_t ZSTD_compress2_c(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
@@ -5392,35 +5423,41 @@ size_t ZSTD_compressStream2_simpleArgs (
}
}
static size_t ZSTD_rust_compress2_resetSession(void* context)
{
return ZSTD_CCtx_reset((ZSTD_CCtx*)context, ZSTD_reset_session_only);
}
static void ZSTD_rust_compress2_setBufferModes(
void* context, int inBufferMode, int outBufferMode)
{
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
cctx->requestedParams.inBufferMode = (ZSTD_bufferMode_e)inBufferMode;
cctx->requestedParams.outBufferMode = (ZSTD_bufferMode_e)outBufferMode;
}
static size_t ZSTD_rust_compress2_streamEnd(
void* context, void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos)
{
return ZSTD_compressStream2_simpleArgs(
(ZSTD_CCtx*)context, dst, dstCapacity, dstPos,
src, srcSize, srcPos, ZSTD_e_end);
}
size_t ZSTD_compress2_c(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;
ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;
ZSTD_rust_compress2State state;
state.callbackContext = cctx;
state.resetSession = ZSTD_rust_compress2_resetSession;
state.setBufferModes = ZSTD_rust_compress2_setBufferModes;
state.compressStreamEnd = ZSTD_rust_compress2_streamEnd;
state.originalInBufferMode = (int)cctx->requestedParams.inBufferMode;
state.originalOutBufferMode = (int)cctx->requestedParams.outBufferMode;
DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
/* Enable stable input/output buffers. */
cctx->requestedParams.inBufferMode = ZSTD_bm_stable;
cctx->requestedParams.outBufferMode = ZSTD_bm_stable;
{ size_t oPos = 0;
size_t iPos = 0;
size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
dst, dstCapacity, &oPos,
src, srcSize, &iPos,
ZSTD_e_end);
/* Reset to the original values. */
cctx->requestedParams.inBufferMode = originalInBufferMode;
cctx->requestedParams.outBufferMode = originalOutBufferMode;
FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
if (result != 0) { /* compression not completed, due to lack of output space */
assert(oPos == dstCapacity);
RETURN_ERROR(dstSize_tooSmall, "");
}
assert(iPos == srcSize); /* all input is expected consumed */
return oPos;
}
return ZSTD_rust_compress2(&state, dst, dstCapacity, src, srcSize);
}
/* The explicit-delimiter adapter is also used by the external sequence