refactor(compress): move stable buffer policy to Rust

Move the stable input and output expectation update into the Rust compression
module. Keep the private CCtx layout and debug logging in the C adapter while
passing only the buffer-mode scalars and projected buffer fields across the
ABI. Preserve C size_t wrapping for the output remainder and leave buffered
modes unchanged.

Test Plan:
- rustfmt --edition 2021 --check rust/src/zstd_compress.rs
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets
- ulimit -v 41943040; make -j1 -C tests test
This commit is contained in:
2026-07-20 05:42:18 +02:00
parent f3a2caa0e2
commit 2d23838112
2 changed files with 127 additions and 6 deletions
+11 -6
View File
@@ -1792,6 +1792,10 @@ size_t ZSTD_rust_checkBufferStability(
const void* expectedInSrc, size_t expectedInPos,
const void* inputSrc, size_t inputPos,
size_t expectedOutBufferSize, size_t outputSize, size_t outputPos);
void ZSTD_rust_setBufferExpectations(
int inBufferMode, int outBufferMode,
ZSTD_inBuffer* expectedInBuffer, size_t* expectedOutBufferSize,
const ZSTD_outBuffer* output, const ZSTD_inBuffer* input);
/* Context-free compression-parameter selection and sizing leaves live in
* Rust (rust/src/zstd_compress_params.rs). This file retains
@@ -7690,12 +7694,13 @@ static void
ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, const ZSTD_outBuffer* output, const ZSTD_inBuffer* input)
{
DEBUGLOG(5, "ZSTD_setBufferExpectations (for advanced stable in/out modes)");
if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
cctx->expectedInBuffer = *input;
}
if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
cctx->expectedOutBufferSize = output->size - output->pos;
}
ZSTD_rust_setBufferExpectations(
(int)cctx->appliedParams.inBufferMode,
(int)cctx->appliedParams.outBufferMode,
&cctx->expectedInBuffer,
&cctx->expectedOutBufferSize,
output,
input);
}
/* Validate that the input/output buffers match the expectations set by
+116
View File
@@ -6169,6 +6169,53 @@ pub extern "C" fn ZSTD_rust_checkBufferStability(
)
}
#[inline]
unsafe fn set_buffer_expectations(
in_buffer_mode: c_int,
out_buffer_mode: c_int,
expected_in_buffer: *mut ZSTD_inBuffer,
expected_out_buffer_size: *mut usize,
output: *const ZSTD_outBuffer,
input: *const ZSTD_inBuffer,
) {
if in_buffer_mode == ZSTD_BM_STABLE {
unsafe {
*expected_in_buffer = ptr::read(input);
}
}
if out_buffer_mode == ZSTD_BM_STABLE {
let output = unsafe { &*output };
unsafe {
*expected_out_buffer_size = output.size.wrapping_sub(output.pos);
}
}
}
/// Update the stable input/output expectations after a compression call.
///
/// C retains the private `ZSTD_CCtx` fields and passes only their projections;
/// Rust owns the buffer-mode policy and C-size arithmetic.
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_setBufferExpectations(
in_buffer_mode: c_int,
out_buffer_mode: c_int,
expected_in_buffer: *mut ZSTD_inBuffer,
expected_out_buffer_size: *mut usize,
output: *const ZSTD_outBuffer,
input: *const ZSTD_inBuffer,
) {
unsafe {
set_buffer_expectations(
in_buffer_mode,
out_buffer_mode,
expected_in_buffer,
expected_out_buffer_size,
output,
input,
);
}
}
#[inline]
fn select_sequence_copier(mode: c_int) -> c_int {
debug_assert!(
@@ -14597,6 +14644,75 @@ mod tests {
);
}
#[test]
fn set_buffer_expectations_updates_only_enabled_stable_modes() {
let expected_src = b"expected".as_ptr().cast::<c_void>();
let input_src = b"input".as_ptr().cast::<c_void>();
let mut expected_input = ZSTD_inBuffer {
src: expected_src,
size: 3,
pos: 1,
};
let input = ZSTD_inBuffer {
src: input_src,
size: 11,
pos: 7,
};
let output = ZSTD_outBuffer {
dst: ptr::null_mut(),
size: 40,
pos: 9,
};
let mut expected_output_size = 5;
unsafe {
ZSTD_rust_setBufferExpectations(
ZSTD_BM_STABLE,
ZSTD_BM_STABLE,
&mut expected_input,
&mut expected_output_size,
&output,
&input,
);
}
assert_eq!(expected_input.src, input.src);
assert_eq!(expected_input.size, input.size);
assert_eq!(expected_input.pos, input.pos);
assert_eq!(expected_output_size, 31);
let original_input_src = expected_input.src;
let original_input_size = expected_input.size;
let original_input_pos = expected_input.pos;
let original_output_size = expected_output_size;
let other_input = ZSTD_inBuffer {
src: expected_src,
size: 99,
pos: 22,
};
let other_output = ZSTD_outBuffer {
dst: ptr::null_mut(),
size: 3,
pos: 8,
};
unsafe {
ZSTD_rust_setBufferExpectations(
ZSTD_BM_BUFFERED,
ZSTD_BM_BUFFERED,
&mut expected_input,
&mut expected_output_size,
&other_output,
&other_input,
);
}
assert_eq!(expected_input.src, original_input_src);
assert_eq!(expected_input.size, original_input_size);
assert_eq!(expected_input.pos, original_input_pos);
assert_eq!(expected_output_size, original_output_size);
}
#[test]
fn sequence_api_plan_places_input_and_frame_checksums_around_blocks() {
assert_eq!(