refactor(cli): move list status policy to Rust

Move the scalar InfoError-to-action mapping used by FIO_listFile into Rust and reuse the same classifier while aggregating multi-file list results. C retains file opening/parsing, exact diagnostics, metadata formatting, private fileInfo_t state, and the public result values; add layout and mapping coverage.

Test Plan: git diff --cached --check; focused Rust mapping test added; full capped verification will run after the MT and dictionary workers are integrated.
This commit is contained in:
2026-07-21 07:35:53 +02:00
parent 484a76757b
commit c522906d07
2 changed files with 95 additions and 8 deletions
+74 -1
View File
@@ -30,6 +30,15 @@ const FIO_MULTI_FILES_ACTION_QUIET_ABORT: c_int = 4;
const FIO_MULTI_FILES_ACTION_CONFIRM: c_int = 5;
const FIO_LIST_INFO_SUCCESS: c_int = 0;
const FIO_LIST_INFO_FRAME_ERROR: c_int = 1;
const FIO_LIST_INFO_NOT_ZSTD: c_int = 2;
const FIO_LIST_INFO_FILE_ERROR: c_int = 3;
const FIO_LIST_INFO_TRUNCATED_INPUT: c_int = 4;
pub const FIO_RUST_LIST_FILE_ACTION_SUCCESS: c_int = 0;
pub const FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR: c_int = 1;
pub const FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD: c_int = 2;
pub const FIO_RUST_LIST_FILE_ACTION_FILE_ERROR: c_int = 3;
pub const FIO_RUST_LIST_FILE_ACTION_TRUNCATED_INPUT: c_int = 4;
pub const FIO_RUST_LIST_FILE_ACTION_INVALID: c_int = 5;
const UTIL_FILESIZE_UNKNOWN: u64 = u64::MAX;
const COMPRESSED_FILE_EXTENSIONS: &[&[u8]] = &[
b".zst",
@@ -704,6 +713,27 @@ pub type FIO_listMultipleFilesListFileFn = unsafe extern "C" fn(
pub type FIO_listMultipleFilesDisplayTotalFn =
unsafe extern "C" fn(*mut c_void, *const FIO_listFileInfoProjection_t);
#[inline]
fn list_file_status_action(status: c_int) -> c_int {
match status {
FIO_LIST_INFO_SUCCESS => FIO_RUST_LIST_FILE_ACTION_SUCCESS,
FIO_LIST_INFO_FRAME_ERROR => FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR,
FIO_LIST_INFO_NOT_ZSTD => FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD,
FIO_LIST_INFO_FILE_ERROR => FIO_RUST_LIST_FILE_ACTION_FILE_ERROR,
FIO_LIST_INFO_TRUNCATED_INPUT => FIO_RUST_LIST_FILE_ACTION_TRUNCATED_INPUT,
_ => FIO_RUST_LIST_FILE_ACTION_INVALID,
}
}
/// Map the C-owned `InfoError` result to the scalar `--list` action.
///
/// C retains the exact diagnostics, file opening/parsing, metadata formatting,
/// and private `fileInfo_t` layout. Rust owns only this status policy.
#[no_mangle]
pub extern "C" fn FIO_rust_listFileStatusAction(status: c_int) -> c_int {
list_file_status_action(status)
}
/// Callback projection for the C-owned `--list` file operations.
#[repr(C)]
pub struct FIO_listMultipleFilesCallbacks_t {
@@ -2203,7 +2233,10 @@ pub unsafe extern "C" fn FIO_rust_listMultipleFiles(
let mut info = FIO_listFileInfoProjection_t::default();
let status = unsafe { list_file(callbacks.opaque, file_name, displayLevel, &mut info) };
error |= status;
if status == FIO_LIST_INFO_SUCCESS || status == FIO_LIST_INFO_FRAME_ERROR {
let action = list_file_status_action(status);
if action == FIO_RUST_LIST_FILE_ACTION_SUCCESS
|| action == FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR
{
total = add_list_file_info(total, info);
}
}
@@ -2539,6 +2572,46 @@ mod tests {
}
}
#[test]
fn list_file_status_action_preserves_cli_mapping_and_abi() {
for (status, action) in [
(
FIO_LIST_INFO_SUCCESS,
FIO_RUST_LIST_FILE_ACTION_SUCCESS,
),
(
FIO_LIST_INFO_FRAME_ERROR,
FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR,
),
(
FIO_LIST_INFO_NOT_ZSTD,
FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD,
),
(
FIO_LIST_INFO_FILE_ERROR,
FIO_RUST_LIST_FILE_ACTION_FILE_ERROR,
),
(
FIO_LIST_INFO_TRUNCATED_INPUT,
FIO_RUST_LIST_FILE_ACTION_TRUNCATED_INPUT,
),
(-1, FIO_RUST_LIST_FILE_ACTION_INVALID),
(5, FIO_RUST_LIST_FILE_ACTION_INVALID),
(c_int::MAX, FIO_RUST_LIST_FILE_ACTION_INVALID),
] {
assert_eq!(
list_file_status_action(status),
action,
"unexpected action for --list status {status}"
);
assert_eq!(
FIO_rust_listFileStatusAction(status),
action,
"C ABI disagrees for --list status {status}"
);
}
}
#[test]
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
let cases = [