diff --git a/programs/fileio.c b/programs/fileio.c index b68dddba4..3c638f37d 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -472,14 +472,17 @@ enum { FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR = 9, FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED = 10 }; +/* Rust owns the decompression status-to-action policy. C keeps the exact + * diagnostic strings and display callback around the resulting action. */ 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 + FIO_RUST_DECOMPRESS_ACTION_NOOP = 0, + FIO_RUST_DECOMPRESS_ACTION_EMPTY_INPUT = 1, + FIO_RUST_DECOMPRESS_ACTION_SHORT_INPUT = 2, + FIO_RUST_DECOMPRESS_ACTION_GZIP_UNSUPPORTED = 3, + FIO_RUST_DECOMPRESS_ACTION_LZMA_UNSUPPORTED = 4, + FIO_RUST_DECOMPRESS_ACTION_LZ4_UNSUPPORTED = 5, + FIO_RUST_DECOMPRESS_ACTION_UNSUPPORTED_FORMAT = 6, + FIO_RUST_DECOMPRESS_ACTION_INVALID = 7 }; typedef int (*FIO_rust_decompress_frame_fn)(void* opaque, const char* srcFileName, @@ -513,7 +516,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); +int FIO_rust_decompressStatusAction(int status); int FIO_rust_decompressPassThroughPolicy(int passThrough, int overwrite, int destinationIsStdout); @@ -4233,25 +4236,27 @@ static void FIO_rust_decompressStatusCallback(void* opaque, const char* srcFileName) { (void)opaque; - switch (FIO_rust_decompressStatusDiagnostic(status)) { - case FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT: + switch (FIO_rust_decompressStatusAction(status)) { + case FIO_RUST_DECOMPRESS_ACTION_EMPTY_INPUT: DISPLAYLEVEL(1, "zstd: %s: unexpected end of file \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT: + case FIO_RUST_DECOMPRESS_ACTION_SHORT_INPUT: DISPLAYLEVEL(1, "zstd: %s: unknown header \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED: + case FIO_RUST_DECOMPRESS_ACTION_GZIP_UNSUPPORTED: DISPLAYLEVEL(1, "zstd: %s: gzip file cannot be uncompressed (zstd compiled without HAVE_ZLIB) -- ignored \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED: + case FIO_RUST_DECOMPRESS_ACTION_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_DIAGNOSTIC_LZ4_UNSUPPORTED: + case FIO_RUST_DECOMPRESS_ACTION_LZ4_UNSUPPORTED: DISPLAYLEVEL(1, "zstd: %s: lz4 file cannot be uncompressed (zstd compiled without HAVE_LZ4) -- ignored \n", srcFileName); break; - case FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT: + case FIO_RUST_DECOMPRESS_ACTION_UNSUPPORTED_FORMAT: DISPLAYLEVEL(1, "zstd: %s: unsupported format \n", srcFileName); break; + case FIO_RUST_DECOMPRESS_ACTION_NOOP: + case FIO_RUST_DECOMPRESS_ACTION_INVALID: default: break; } diff --git a/rust/src/fileio_asyncio.rs b/rust/src/fileio_asyncio.rs index 77408dda4..94b8899a3 100644 --- a/rust/src/fileio_asyncio.rs +++ b/rust/src/fileio_asyncio.rs @@ -56,13 +56,14 @@ 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; +pub const FIO_RUST_DECOMPRESS_ACTION_NOOP: c_int = 0; +pub const FIO_RUST_DECOMPRESS_ACTION_EMPTY_INPUT: c_int = 1; +pub const FIO_RUST_DECOMPRESS_ACTION_SHORT_INPUT: c_int = 2; +pub const FIO_RUST_DECOMPRESS_ACTION_GZIP_UNSUPPORTED: c_int = 3; +pub const FIO_RUST_DECOMPRESS_ACTION_LZMA_UNSUPPORTED: c_int = 4; +pub const FIO_RUST_DECOMPRESS_ACTION_LZ4_UNSUPPORTED: c_int = 5; +pub const FIO_RUST_DECOMPRESS_ACTION_UNSUPPORTED_FORMAT: c_int = 6; +pub const FIO_RUST_DECOMPRESS_ACTION_INVALID: c_int = 7; /// Resolves the legacy automatic pass-through mode without touching the /// destination name or any C-owned file state. Explicit values are returned @@ -89,22 +90,32 @@ pub extern "C" fn FIO_rust_decompressPassThroughPolicy( decompress_pass_through_policy(pass_through, overwrite, destination_is_stdout) } -/// 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 { +/// Maps decompression results to the scalar actions consumed by the C CLI. +/// Rust owns this status policy; C retains the exact diagnostics, source-name +/// handling, and display operations for the returned action. +#[inline] +fn decompress_status_action(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, + FIO_RUST_DECOMPRESS_EMPTY_INPUT => FIO_RUST_DECOMPRESS_ACTION_EMPTY_INPUT, + FIO_RUST_DECOMPRESS_SHORT_INPUT => FIO_RUST_DECOMPRESS_ACTION_SHORT_INPUT, + FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED => FIO_RUST_DECOMPRESS_ACTION_GZIP_UNSUPPORTED, + FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED => FIO_RUST_DECOMPRESS_ACTION_LZMA_UNSUPPORTED, + FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED => FIO_RUST_DECOMPRESS_ACTION_LZ4_UNSUPPORTED, + FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT => FIO_RUST_DECOMPRESS_ACTION_UNSUPPORTED_FORMAT, + 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 => FIO_RUST_DECOMPRESS_ACTION_NOOP, + _ => FIO_RUST_DECOMPRESS_ACTION_INVALID, } } +#[no_mangle] +pub extern "C" fn FIO_rust_decompressStatusAction(status: c_int) -> c_int { + decompress_status_action(status) +} + 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; @@ -5344,48 +5355,62 @@ mod tests { } #[test] - fn decompression_status_diagnostic_preserves_cli_mapping() { - for (status, diagnostic) in [ + fn decompression_status_action_preserves_cli_mapping_and_abi() { + for (status, action) in [ + (FIO_RUST_DECOMPRESS_OK, FIO_RUST_DECOMPRESS_ACTION_NOOP), + ( + FIO_RUST_DECOMPRESS_PASS_THROUGH, + FIO_RUST_DECOMPRESS_ACTION_NOOP, + ), ( FIO_RUST_DECOMPRESS_EMPTY_INPUT, - FIO_RUST_DECOMPRESS_DIAGNOSTIC_EMPTY_INPUT, + FIO_RUST_DECOMPRESS_ACTION_EMPTY_INPUT, ), ( FIO_RUST_DECOMPRESS_SHORT_INPUT, - FIO_RUST_DECOMPRESS_DIAGNOSTIC_SHORT_INPUT, + FIO_RUST_DECOMPRESS_ACTION_SHORT_INPUT, ), ( FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED, - FIO_RUST_DECOMPRESS_DIAGNOSTIC_GZIP_UNSUPPORTED, + FIO_RUST_DECOMPRESS_ACTION_GZIP_UNSUPPORTED, ), ( FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED, - FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZMA_UNSUPPORTED, + FIO_RUST_DECOMPRESS_ACTION_LZMA_UNSUPPORTED, ), ( FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED, - FIO_RUST_DECOMPRESS_DIAGNOSTIC_LZ4_UNSUPPORTED, + FIO_RUST_DECOMPRESS_ACTION_LZ4_UNSUPPORTED, ), ( FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT, - FIO_RUST_DECOMPRESS_DIAGNOSTIC_UNSUPPORTED_FORMAT, + FIO_RUST_DECOMPRESS_ACTION_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, + ( + FIO_RUST_DECOMPRESS_FRAME_ERROR, + FIO_RUST_DECOMPRESS_ACTION_NOOP, + ), + ( + FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR, + FIO_RUST_DECOMPRESS_ACTION_NOOP, + ), + ( + FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED, + FIO_RUST_DECOMPRESS_ACTION_NOOP, + ), + (-1, FIO_RUST_DECOMPRESS_ACTION_INVALID), + (11, FIO_RUST_DECOMPRESS_ACTION_INVALID), + (c_int::MAX, FIO_RUST_DECOMPRESS_ACTION_INVALID), ] { assert_eq!( - FIO_rust_decompressStatusDiagnostic(status), - FIO_RUST_DECOMPRESS_DIAGNOSTIC_NONE + decompress_status_action(status), + action, + "unexpected action for decompression status {status}" + ); + assert_eq!( + FIO_rust_decompressStatusAction(status), + action, + "C ABI disagrees for decompression status {status}" ); } }