feat(compress): return frame progression from Rust
Complete the single-thread branch of ZSTD_getFrameProgression behind a narrow scalar ABI boundary. C still owns the public entry point, buffered input extraction, assertions, and the multithreaded dispatch; Rust now owns the six-field single-thread result construction. The Rust #[repr(C)] result uses wrapping u64 conversion for consumed input plus buffered size, mirrors produced into flushed, and zeros the MT-only fields. This replaces the earlier ingested-only helper so the ABI no longer splits one result across duplicate C and Rust construction paths. The unit tests now cover the complete result and its u64 wrapping behavior. Test Plan: - All three requested compression clippy commands passed before and after `cargo +nightly fmt --manifest-path rust/Cargo.toml`. - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression` -- 327 passed. - `make -B -C lib -j2 lib` -- passed. - `make -C tests test-rust-lib-smoke` -- passed. - `tests/fuzzer -s4560 -t56 -i57 -v` -- passed. - `make -C tests -j2 test-zstream` -- passed: 84 named, 5,330, and 9,772 randomized cases. - `git diff --check` and `git diff --cached --check` -- passed. The zstream build retains the pre-existing warning at `tests/zstreamtest.c:1899` about an unterminated initializer string.
This commit is contained in:
+54
-27
@@ -29,7 +29,7 @@ use crate::zstd_compress_stats::{SeqStore_t, ZSTD_compressedBlockState_t};
|
||||
use crate::zstd_compress_superblock::ZSTD_rust_compressSuperBlock;
|
||||
use std::ffi::c_void;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
use std::os::raw::c_int;
|
||||
use std::os::raw::{c_int, c_uint};
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(not(test))]
|
||||
@@ -345,19 +345,43 @@ pub unsafe extern "C" fn ZSTD_rust_updateFrameProgression(
|
||||
) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn frame_progression_ingested(consumed_src_size: u64, buffered: usize) -> u64 {
|
||||
// C's usual arithmetic conversions promote size_t to U64 before wrapping.
|
||||
consumed_src_size.wrapping_add(buffered as u64)
|
||||
/// ABI-compatible representation of `ZSTD_frameProgression` from `zstd.h`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ZSTD_frameProgression {
|
||||
pub ingested: u64,
|
||||
pub consumed: u64,
|
||||
pub produced: u64,
|
||||
pub flushed: u64,
|
||||
pub currentJobID: c_uint,
|
||||
pub nbActiveWorkers: c_uint,
|
||||
}
|
||||
|
||||
/// Calculate single-threaded frame input progression from consumed and buffered input.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ZSTD_rust_frameProgressionIngested(
|
||||
#[inline]
|
||||
fn frame_progression(
|
||||
consumed_src_size: u64,
|
||||
buffered: usize,
|
||||
) -> u64 {
|
||||
frame_progression_ingested(consumed_src_size, buffered)
|
||||
produced_c_size: u64,
|
||||
) -> ZSTD_frameProgression {
|
||||
ZSTD_frameProgression {
|
||||
// C's usual arithmetic conversions promote size_t to U64 before wrapping.
|
||||
ingested: consumed_src_size.wrapping_add(buffered as u64),
|
||||
consumed: consumed_src_size,
|
||||
produced: produced_c_size,
|
||||
flushed: produced_c_size,
|
||||
currentJobID: 0,
|
||||
nbActiveWorkers: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct single-threaded frame progression from C-owned scalar state.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ZSTD_rust_frameProgression(
|
||||
consumed_src_size: u64,
|
||||
buffered: usize,
|
||||
produced_c_size: u64,
|
||||
) -> ZSTD_frameProgression {
|
||||
frame_progression(consumed_src_size, buffered, produced_c_size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -1435,35 +1459,38 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_progression_ingested_handles_zero() {
|
||||
assert_eq!(frame_progression_ingested(0, 0), 0);
|
||||
assert_eq!(ZSTD_rust_frameProgressionIngested(0, 0), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_progression_ingested_adds_consumed_and_buffered_input() {
|
||||
fn frame_progression_constructs_single_thread_values() {
|
||||
let consumed = 11_u64;
|
||||
let buffered = 37_usize;
|
||||
let expected = consumed + buffered as u64;
|
||||
let produced = 53_u64;
|
||||
let expected = ZSTD_frameProgression {
|
||||
ingested: consumed + buffered as u64,
|
||||
consumed,
|
||||
produced,
|
||||
flushed: produced,
|
||||
currentJobID: 0,
|
||||
nbActiveWorkers: 0,
|
||||
};
|
||||
|
||||
assert_eq!(frame_progression_ingested(consumed, buffered), expected);
|
||||
assert_eq!(frame_progression(consumed, buffered, produced), expected);
|
||||
assert_eq!(
|
||||
ZSTD_rust_frameProgressionIngested(consumed, buffered),
|
||||
ZSTD_rust_frameProgression(consumed, buffered, produced),
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_progression_ingested_wraps_u64() {
|
||||
fn frame_progression_wraps_buffered_input_to_u64() {
|
||||
let consumed = u64::MAX - 3;
|
||||
let buffered = 8_usize;
|
||||
let expected = consumed.wrapping_add(buffered as u64);
|
||||
let progression = ZSTD_rust_frameProgression(consumed, buffered, 17);
|
||||
|
||||
assert_eq!(frame_progression_ingested(consumed, buffered), expected);
|
||||
assert_eq!(
|
||||
ZSTD_rust_frameProgressionIngested(consumed, buffered),
|
||||
expected
|
||||
);
|
||||
assert_eq!(progression.ingested, consumed.wrapping_add(buffered as u64));
|
||||
assert_eq!(progression.consumed, consumed);
|
||||
assert_eq!(progression.produced, 17);
|
||||
assert_eq!(progression.flushed, 17);
|
||||
assert_eq!(progression.currentJobID, 0);
|
||||
assert_eq!(progression.nbActiveWorkers, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user