From 9cfbb7bebb987aa789f476b990d777d45e6c6645 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Mon, 20 Jul 2026 06:21:14 +0200 Subject: [PATCH] refactor(cli): move decompression diagnostic mapping to Rust Move the status-to-diagnostic policy for decompression failures into the Rust fileio layer. C retains the user-facing strings and callback display logic, while Rust returns a stable diagnostic classification across the ABI and leaves silent statuses silent. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets (775 passed) - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets (179 passed) - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test (all tests completed successfully) --- programs/fileio.c | 24 +++++++++---- rust/src/fileio_asyncio.rs | 71 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 644b17b69..b5aa2b27c 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -434,6 +434,15 @@ enum { FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR = 9, FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED = 10 }; +enum { + FIO_RUST_DECOMPRESS_DIAGNOSTIC_NONE = 0, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT = 1, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT = 2, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED = 3, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED = 4, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZ4_UNSUPPORTED = 5, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT = 6 +}; typedef int (*FIO_rust_decompress_frame_fn)(void* opaque, const char* srcFileName, U64 alreadyDecoded, @@ -466,6 +475,7 @@ int FIO_rust_finishDecompressFrames(int status, const char* srcFileName, U64 decodedSize, const FIO_rust_decompress_callbacks_t* callbacks); +int FIO_rust_decompressStatusDiagnostic(int status); typedef void (*FIO_rust_decompress_read_fill_fn)( void* opaque, size_t requested, const unsigned char** buffer, size_t* loaded); @@ -4122,23 +4132,23 @@ static void FIO_rust_decompressStatusCallback(void* opaque, const char* srcFileName) { (void)opaque; - switch (status) { - case FIO_RUST_DECOMPRESS_EMPTY_INPUT: + switch (FIO_rust_decompressStatusDiagnostic(status)) { + case FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT: DISPLAYLEVEL(1, "zstd: %s: unexpected end of file \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_SHORT_INPUT: + case FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT: DISPLAYLEVEL(1, "zstd: %s: unknown header \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED: + case FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED: DISPLAYLEVEL(1, "zstd: %s: gzip file cannot be uncompressed (zstd compiled without HAVE_ZLIB) -- ignored \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED: + case FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED: DISPLAYLEVEL(1, "zstd: %s: xz/lzma file cannot be uncompressed (zstd compiled without HAVE_LZMA) -- ignored \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED: + case FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZ4_UNSUPPORTED: DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT: + case FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT: DISPLAYLEVEL(1, "zstd: %s: unsupported format \n", srcFileName); break; default: diff --git a/rust/src/fileio_asyncio.rs b/rust/src/fileio_asyncio.rs index 2656e5afe..a14067e9e 100644 --- a/rust/src/fileio_asyncio.rs +++ b/rust/src/fileio_asyncio.rs @@ -49,6 +49,30 @@ pub const FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT: c_int = 8; pub const FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR: c_int = 9; pub const FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED: c_int = 10; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_NONE: c_int = 0; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT: c_int = 1; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT: c_int = 2; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED: c_int = 3; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED: c_int = 4; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZ4_UNSUPPORTED: c_int = 5; +pub const FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT: c_int = 6; + +/// Maps decompression results to the diagnostics that the C CLI displays. +/// Statuses without a legacy diagnostic deliberately map to `NONE`, retaining +/// the previous C callback's silent default case. +#[no_mangle] +pub extern "C" fn FIO_rust_decompressStatusDiagnostic(status: c_int) -> c_int { + match status { + FIO_RUST_DECOMPRESS_EMPTY_INPUT => FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT, + FIO_RUST_DECOMPRESS_SHORT_INPUT => FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT, + FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED => FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED, + FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED => FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED, + FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED => FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZ4_UNSUPPORTED, + FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT => FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT, + _ => FIO_RUST_DECOMPRESS_DIAGNOSTIC_NONE, + } +} + type FIO_rust_frame_progress_fn = Option; pub type FIO_rust_decompress_frame_fn = unsafe extern "C" fn(*mut c_void, *const c_char, u64, *mut u64, *mut usize, c_int) -> c_int; @@ -5011,6 +5035,53 @@ impl PoolInner { mod tests { use super::*; + #[test] + fn decompression_status_diagnostic_preserves_cli_mapping() { + for (status, diagnostic) in [ + ( + FIO_RUST_DECOMPRESS_EMPTY_INPUT, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT, + ), + ( + FIO_RUST_DECOMPRESS_SHORT_INPUT, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT, + ), + ( + FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED, + ), + ( + FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED, + ), + ( + FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZ4_UNSUPPORTED, + ), + ( + FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT, + FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT, + ), + ] { + assert_eq!(FIO_rust_decompressStatusDiagnostic(status), diagnostic); + } + + for status in [ + FIO_RUST_DECOMPRESS_OK, + FIO_RUST_DECOMPRESS_PASS_THROUGH, + FIO_RUST_DECOMPRESS_FRAME_ERROR, + FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR, + FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED, + -1, + 99, + ] { + assert_eq!( + FIO_rust_decompressStatusDiagnostic(status), + FIO_RUST_DECOMPRESS_DIAGNOSTIC_NONE + ); + } + } + const SOURCE_POLICY_STAT: u8 = 1; const SOURCE_POLICY_EXCLUDED: u8 = 2; const SOURCE_POLICY_OPEN: u8 = 3;