refactor(cli): move zstd frame action policy to Rust

Project the zstd frame decoder status into a Rust action classification while
preserving C-owned diagnostics, error-help formatting, private resources, and
exact decoding return values. Unknown statuses retain the assertion fallback
and the existing frame-decoding error result.

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 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:
2026-07-20 19:05:43 +02:00
parent ffc52de643
commit d9515fcf96
2 changed files with 90 additions and 15 deletions
+23 -15
View File
@@ -404,6 +404,13 @@ enum {
FIO_RUST_ZSTD_FRAME_DECODING_ERROR = 1,
FIO_RUST_ZSTD_FRAME_PREMATURE_END = 2,
};
enum {
FIO_RUST_ZSTD_FRAME_ACTION_OK = 0,
FIO_RUST_ZSTD_FRAME_ACTION_DECODING_ERROR = 1,
FIO_RUST_ZSTD_FRAME_ACTION_PREMATURE_END = 2,
FIO_RUST_ZSTD_FRAME_ACTION_INVALID = 3,
};
int FIO_rust_decompressZstdFrameAction(int status);
typedef void (*FIO_rust_frame_progress_fn)(void* opaque,
const char* srcFileName,
U64 decodedSize);
@@ -3786,23 +3793,24 @@ FIO_decompressZstdFrames(FIO_ctx_t* const fCtx, dRess_t* ress,
fCtx, ress->dctx, ress->readCtx, ress->writeCtx, srcFileName,
alreadyDecoded, &decodedSize, &zstdError,
FIO_decompressZstdFrameProgress);
int const action = FIO_rust_decompressZstdFrameAction(status);
if (status == FIO_RUST_ZSTD_FRAME_OK)
return decodedSize;
if (status == FIO_RUST_ZSTD_FRAME_DECODING_ERROR) {
DISPLAYLEVEL(1, "%s : Decoding error (36) : %s \n",
srcFileName, ZSTD_getErrorName(zstdError));
FIO_zstdErrorHelp(prefs, ress, zstdError, srcFileName);
return FIO_ERROR_FRAME_DECODING;
switch (action) {
case FIO_RUST_ZSTD_FRAME_ACTION_OK:
return decodedSize;
case FIO_RUST_ZSTD_FRAME_ACTION_DECODING_ERROR:
DISPLAYLEVEL(1, "%s : Decoding error (36) : %s \n",
srcFileName, ZSTD_getErrorName(zstdError));
FIO_zstdErrorHelp(prefs, ress, zstdError, srcFileName);
return FIO_ERROR_FRAME_DECODING;
case FIO_RUST_ZSTD_FRAME_ACTION_PREMATURE_END:
DISPLAYLEVEL(1, "%s : Read error (39) : premature end \n",
srcFileName);
return FIO_ERROR_FRAME_DECODING;
default:
assert(0);
return FIO_ERROR_FRAME_DECODING;
}
if (status == FIO_RUST_ZSTD_FRAME_PREMATURE_END) {
DISPLAYLEVEL(1, "%s : Read error (39) : premature end \n",
srcFileName);
return FIO_ERROR_FRAME_DECODING;
}
assert(0);
return FIO_ERROR_FRAME_DECODING;
}
+67
View File
@@ -348,6 +348,42 @@ const FIO_RUST_ZSTD_ERROR_HELP_WINDOW_GUIDANCE: c_int = 1;
#[cfg(feature = "decompression")]
const FIO_RUST_ZSTD_ERROR_HELP_UNSUPPORTED_WINDOW_LOG: c_int = 2;
#[cfg(feature = "decompression")]
const FIO_RUST_ZSTD_FRAME_OK: c_int = 0;
#[cfg(feature = "decompression")]
const FIO_RUST_ZSTD_FRAME_DECODING_ERROR: c_int = 1;
#[cfg(feature = "decompression")]
const FIO_RUST_ZSTD_FRAME_PREMATURE_END: c_int = 2;
#[cfg(feature = "decompression")]
pub const FIO_RUST_ZSTD_FRAME_ACTION_OK: c_int = 0;
#[cfg(feature = "decompression")]
pub const FIO_RUST_ZSTD_FRAME_ACTION_DECODING_ERROR: c_int = 1;
#[cfg(feature = "decompression")]
pub const FIO_RUST_ZSTD_FRAME_ACTION_PREMATURE_END: c_int = 2;
#[cfg(feature = "decompression")]
pub const FIO_RUST_ZSTD_FRAME_ACTION_INVALID: c_int = 3;
#[cfg(feature = "decompression")]
#[inline]
fn decompress_zstd_frame_action(status: c_int) -> c_int {
match status {
FIO_RUST_ZSTD_FRAME_OK => FIO_RUST_ZSTD_FRAME_ACTION_OK,
FIO_RUST_ZSTD_FRAME_DECODING_ERROR => FIO_RUST_ZSTD_FRAME_ACTION_DECODING_ERROR,
FIO_RUST_ZSTD_FRAME_PREMATURE_END => FIO_RUST_ZSTD_FRAME_ACTION_PREMATURE_END,
_ => FIO_RUST_ZSTD_FRAME_ACTION_INVALID,
}
}
/// Classify a zstd-frame status without owning the CLI's diagnostics or
/// private decompression resources. C keeps the exact messages, error-help
/// call, and return values for each resulting action.
#[cfg(feature = "decompression")]
#[no_mangle]
pub extern "C" fn FIO_rust_decompressZstdFrameAction(status: c_int) -> c_int {
decompress_zstd_frame_action(status)
}
#[cfg(feature = "decompression")]
type FIO_rust_zstdErrorHelpDisplayFn =
unsafe extern "C" fn(*mut c_void, c_int, *const c_char, u64, c_uint, c_uint, c_uint);
@@ -2460,6 +2496,37 @@ mod tests {
use std::fs;
use std::mem::{align_of, offset_of, size_of};
#[cfg(feature = "decompression")]
#[test]
fn decompress_zstd_frame_action_preserves_status_classes() {
let cases = [
(FIO_RUST_ZSTD_FRAME_OK, FIO_RUST_ZSTD_FRAME_ACTION_OK),
(
FIO_RUST_ZSTD_FRAME_DECODING_ERROR,
FIO_RUST_ZSTD_FRAME_ACTION_DECODING_ERROR,
),
(
FIO_RUST_ZSTD_FRAME_PREMATURE_END,
FIO_RUST_ZSTD_FRAME_ACTION_PREMATURE_END,
),
(-1, FIO_RUST_ZSTD_FRAME_ACTION_INVALID),
(3, FIO_RUST_ZSTD_FRAME_ACTION_INVALID),
];
for (status, expected_action) in cases {
assert_eq!(
decompress_zstd_frame_action(status),
expected_action,
"unexpected action for zstd frame status {status}"
);
assert_eq!(
FIO_rust_decompressZstdFrameAction(status),
expected_action,
"export disagrees for zstd frame status {status}"
);
}
}
#[test]
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
let cases = [