refactor(cli): derive window error log in Rust
Move the historical ceil(log2(windowSize)) calculation used by FIO_zstdErrorHelp into Rust. C retains frame-header parsing, private read-pool access, the ABI slot, callbacks, diagnostics, and output formatting. The zero-size and non-power-of-two behavior remains explicit and tested at the u64 boundary. Test Plan: - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings` -- passed - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings` -- passed - `ulimit -v 41943040; cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check` -- passed - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets` -- passed, 190 tests - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1` -- passed - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 ./tests/rustLibSmoke` -- passed - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1 -C tests test` -- passed, including large streaming, native, fuzzer, and zstream phases
This commit is contained in:
+1
-5
@@ -3654,7 +3654,7 @@ typedef struct {
|
||||
const char* srcFileName;
|
||||
unsigned long long windowSize;
|
||||
size_t headerError;
|
||||
unsigned windowLog;
|
||||
unsigned windowLog; /* Rust derives this from windowSize; retain ABI layout. */
|
||||
unsigned memLimit;
|
||||
int errorCode;
|
||||
FIO_rust_zstdErrorHelpDisplayFn display;
|
||||
@@ -3725,7 +3725,6 @@ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs,
|
||||
int const errorCode = (int)ZSTD_getErrorCode(err);
|
||||
size_t headerError = 1;
|
||||
unsigned long long windowSize = 0;
|
||||
unsigned windowLog = 0;
|
||||
unsigned memLimit = 0;
|
||||
FIO_rust_zstdErrorHelpState state = { 0 };
|
||||
|
||||
@@ -3735,8 +3734,6 @@ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs,
|
||||
&header, ress->readCtx->srcBuffer, ress->readCtx->srcBufferLoaded);
|
||||
if (headerError == 0) {
|
||||
windowSize = header.windowSize;
|
||||
windowLog = FIO_highbit64(windowSize)
|
||||
+ ((windowSize & (windowSize - 1)) != 0);
|
||||
memLimit = prefs->memLimit;
|
||||
}
|
||||
}
|
||||
@@ -3745,7 +3742,6 @@ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs,
|
||||
state.srcFileName = srcFileName;
|
||||
state.windowSize = windowSize;
|
||||
state.headerError = headerError;
|
||||
state.windowLog = windowLog;
|
||||
state.memLimit = memLimit;
|
||||
state.errorCode = errorCode;
|
||||
state.display = FIO_rust_zstdErrorHelp_display;
|
||||
|
||||
+47
-12
@@ -390,9 +390,10 @@ type FIO_rust_zstdErrorHelpDisplayFn =
|
||||
|
||||
/// Scalar projection for the zstd window-size error diagnostic.
|
||||
///
|
||||
/// C keeps frame-header decoding, window-log extraction, and output formatting
|
||||
/// in C. Rust owns the error filter and selects the concrete or unsupported
|
||||
/// diagnostic through the display callback.
|
||||
/// C keeps frame-header decoding and output formatting in C. Rust derives the
|
||||
/// historical window log, owns the error filter, and selects the concrete or
|
||||
/// unsupported diagnostic through the display callback. The `window_log`
|
||||
/// projection field remains part of the C ABI layout but is not consumed.
|
||||
#[cfg(feature = "decompression")]
|
||||
#[repr(C)]
|
||||
pub struct FIO_rust_zstdErrorHelpState {
|
||||
@@ -406,6 +407,16 @@ pub struct FIO_rust_zstdErrorHelpState {
|
||||
display: Option<FIO_rust_zstdErrorHelpDisplayFn>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "decompression")]
|
||||
#[inline]
|
||||
fn ceil_log2_window_size(window_size: u64) -> c_uint {
|
||||
if window_size == 0 {
|
||||
return 0;
|
||||
}
|
||||
highbit64(window_size)
|
||||
+ c_uint::from((window_size & window_size.wrapping_sub(1)) != 0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "decompression")]
|
||||
const _: () = {
|
||||
let callback_offset = (offset_of!(FIO_rust_zstdErrorHelpState, error_code)
|
||||
@@ -448,6 +459,7 @@ pub unsafe extern "C" fn FIO_rust_zstdErrorHelp(state: *const FIO_rust_zstdError
|
||||
let Some(display) = state.display else {
|
||||
return;
|
||||
};
|
||||
let window_log = ceil_log2_window_size(state.window_size);
|
||||
|
||||
if state.header_error == 0 {
|
||||
assert!(state.mem_limit > 0);
|
||||
@@ -457,12 +469,12 @@ pub unsafe extern "C" fn FIO_rust_zstdErrorHelp(state: *const FIO_rust_zstdError
|
||||
FIO_RUST_ZSTD_ERROR_HELP_WINDOW_SIZE,
|
||||
state.src_file_name,
|
||||
state.window_size,
|
||||
state.window_log,
|
||||
window_log,
|
||||
0,
|
||||
state.mem_limit,
|
||||
);
|
||||
}
|
||||
if state.window_log <= ZSTD_WINDOWLOG_MAX {
|
||||
if window_log <= ZSTD_WINDOWLOG_MAX {
|
||||
let window_mb = ((state.window_size >> 20)
|
||||
+ u64::from((state.window_size & ((1u64 << 20) - 1)) != 0))
|
||||
as c_uint;
|
||||
@@ -473,7 +485,7 @@ pub unsafe extern "C" fn FIO_rust_zstdErrorHelp(state: *const FIO_rust_zstdError
|
||||
FIO_RUST_ZSTD_ERROR_HELP_WINDOW_GUIDANCE,
|
||||
state.src_file_name,
|
||||
state.window_size,
|
||||
state.window_log,
|
||||
window_log,
|
||||
window_mb,
|
||||
state.mem_limit,
|
||||
);
|
||||
@@ -488,7 +500,7 @@ pub unsafe extern "C" fn FIO_rust_zstdErrorHelp(state: *const FIO_rust_zstdError
|
||||
FIO_RUST_ZSTD_ERROR_HELP_UNSUPPORTED_WINDOW_LOG,
|
||||
state.src_file_name,
|
||||
state.window_size,
|
||||
state.window_log,
|
||||
window_log,
|
||||
0,
|
||||
state.mem_limit,
|
||||
);
|
||||
@@ -2700,7 +2712,6 @@ mod tests {
|
||||
error_code: c_int,
|
||||
header_error: usize,
|
||||
window_size: u64,
|
||||
window_log: c_uint,
|
||||
mem_limit: c_uint,
|
||||
) -> FIO_rust_zstdErrorHelpState {
|
||||
FIO_rust_zstdErrorHelpState {
|
||||
@@ -2708,18 +2719,44 @@ mod tests {
|
||||
src_file_name: ptr::null(),
|
||||
window_size,
|
||||
header_error,
|
||||
window_log,
|
||||
window_log: c_uint::MAX,
|
||||
mem_limit,
|
||||
error_code,
|
||||
display: Some(zstd_error_help_display_test),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "decompression")]
|
||||
#[test]
|
||||
fn ceil_log2_window_size_handles_zero_powers_non_powers_and_boundaries() {
|
||||
let cases = [
|
||||
(0, 0),
|
||||
(1, 0),
|
||||
(2, 1),
|
||||
(4, 2),
|
||||
(3, 2),
|
||||
(5, 3),
|
||||
((1u64 << 63) - 1, 63),
|
||||
(1u64 << 63, 63),
|
||||
((1u64 << 63) + 1, 64),
|
||||
(u64::MAX - 1, 64),
|
||||
(u64::MAX, 64),
|
||||
];
|
||||
|
||||
for (window_size, expected_window_log) in cases {
|
||||
assert_eq!(
|
||||
ceil_log2_window_size(window_size),
|
||||
expected_window_log,
|
||||
"unexpected window log for window size {window_size}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "decompression")]
|
||||
#[test]
|
||||
fn zstd_error_help_ignores_irrelevant_errors() {
|
||||
let mut context = ZstdErrorHelpTestState::default();
|
||||
let state = zstd_error_help_test_state(&mut context, 0, 0, 8u64 << 20, 23, 64);
|
||||
let state = zstd_error_help_test_state(&mut context, 0, 0, 8u64 << 20, 64);
|
||||
|
||||
unsafe { FIO_rust_zstdErrorHelp(&state) };
|
||||
|
||||
@@ -2735,7 +2772,6 @@ mod tests {
|
||||
ZSTD_ERROR_FRAME_PARAMETER_WINDOW_TOO_LARGE,
|
||||
0,
|
||||
9u64 << 20,
|
||||
24,
|
||||
64,
|
||||
);
|
||||
|
||||
@@ -2766,7 +2802,6 @@ mod tests {
|
||||
ZSTD_ERROR_FRAME_PARAMETER_WINDOW_TOO_LARGE,
|
||||
0,
|
||||
1u64 << window_log,
|
||||
window_log,
|
||||
64,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user