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:
+21
-7
@@ -4743,6 +4743,18 @@ typedef enum {
|
|||||||
info_truncated_input=4
|
info_truncated_input=4
|
||||||
} InfoError;
|
} InfoError;
|
||||||
|
|
||||||
|
/* Rust owns the scalar --list file-status action policy. C keeps the exact
|
||||||
|
* diagnostics, metadata formatting, file I/O, and private fileInfo_t layout. */
|
||||||
|
enum {
|
||||||
|
FIO_RUST_LIST_FILE_ACTION_SUCCESS = 0,
|
||||||
|
FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR = 1,
|
||||||
|
FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD = 2,
|
||||||
|
FIO_RUST_LIST_FILE_ACTION_FILE_ERROR = 3,
|
||||||
|
FIO_RUST_LIST_FILE_ACTION_TRUNCATED_INPUT = 4,
|
||||||
|
FIO_RUST_LIST_FILE_ACTION_INVALID = 5
|
||||||
|
};
|
||||||
|
int FIO_rust_listFileStatusAction(int status);
|
||||||
|
|
||||||
/* Keep the private fileInfo_t layout in C. This projection contains only the
|
/* Keep the private fileInfo_t layout in C. This projection contains only the
|
||||||
* fields needed by the --list total row and crosses the Rust policy boundary
|
* fields needed by the --list total row and crosses the Rust policy boundary
|
||||||
* after FIO_listFile has finished its C-owned open/parse/display work. */
|
* after FIO_listFile has finished its C-owned open/parse/display work. */
|
||||||
@@ -4943,24 +4955,25 @@ FIO_listFile(const char* inFileName, int displayLevel,
|
|||||||
fileInfo_t info;
|
fileInfo_t info;
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
{ InfoError const error = getFileInfo(&info, inFileName);
|
{ InfoError const error = getFileInfo(&info, inFileName);
|
||||||
switch (error) {
|
int const action = FIO_rust_listFileStatusAction((int)error);
|
||||||
case info_frame_error:
|
switch (action) {
|
||||||
|
case FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR:
|
||||||
/* display error, but provide output */
|
/* display error, but provide output */
|
||||||
DISPLAYLEVEL(1, "Error while parsing \"%s\" \n", inFileName);
|
DISPLAYLEVEL(1, "Error while parsing \"%s\" \n", inFileName);
|
||||||
break;
|
break;
|
||||||
case info_not_zstd:
|
case FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD:
|
||||||
DISPLAYOUT("File \"%s\" not compressed by zstd \n", inFileName);
|
DISPLAYOUT("File \"%s\" not compressed by zstd \n", inFileName);
|
||||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||||
return 1;
|
return 1;
|
||||||
case info_file_error:
|
case FIO_RUST_LIST_FILE_ACTION_FILE_ERROR:
|
||||||
/* error occurred while opening the file */
|
/* error occurred while opening the file */
|
||||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||||
return 1;
|
return 1;
|
||||||
case info_truncated_input:
|
case FIO_RUST_LIST_FILE_ACTION_TRUNCATED_INPUT:
|
||||||
DISPLAYOUT("File \"%s\" is truncated \n", inFileName);
|
DISPLAYOUT("File \"%s\" is truncated \n", inFileName);
|
||||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||||
return 1;
|
return 1;
|
||||||
case info_success:
|
case FIO_RUST_LIST_FILE_ACTION_SUCCESS:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4973,7 +4986,8 @@ FIO_listFile(const char* inFileName, int displayLevel,
|
|||||||
output->decompUnavailable = info.decompUnavailable;
|
output->decompUnavailable = info.decompUnavailable;
|
||||||
output->usesCheck = info.usesCheck;
|
output->usesCheck = info.usesCheck;
|
||||||
output->nbFiles = info.nbFiles;
|
output->nbFiles = info.nbFiles;
|
||||||
assert(error == info_success || error == info_frame_error);
|
assert(action == FIO_RUST_LIST_FILE_ACTION_SUCCESS
|
||||||
|
|| action == FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR);
|
||||||
return (int)error;
|
return (int)error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_MULTI_FILES_ACTION_CONFIRM: c_int = 5;
|
||||||
const FIO_LIST_INFO_SUCCESS: c_int = 0;
|
const FIO_LIST_INFO_SUCCESS: c_int = 0;
|
||||||
const FIO_LIST_INFO_FRAME_ERROR: c_int = 1;
|
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 UTIL_FILESIZE_UNKNOWN: u64 = u64::MAX;
|
||||||
const COMPRESSED_FILE_EXTENSIONS: &[&[u8]] = &[
|
const COMPRESSED_FILE_EXTENSIONS: &[&[u8]] = &[
|
||||||
b".zst",
|
b".zst",
|
||||||
@@ -704,6 +713,27 @@ pub type FIO_listMultipleFilesListFileFn = unsafe extern "C" fn(
|
|||||||
pub type FIO_listMultipleFilesDisplayTotalFn =
|
pub type FIO_listMultipleFilesDisplayTotalFn =
|
||||||
unsafe extern "C" fn(*mut c_void, *const FIO_listFileInfoProjection_t);
|
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.
|
/// Callback projection for the C-owned `--list` file operations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct FIO_listMultipleFilesCallbacks_t {
|
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 mut info = FIO_listFileInfoProjection_t::default();
|
||||||
let status = unsafe { list_file(callbacks.opaque, file_name, displayLevel, &mut info) };
|
let status = unsafe { list_file(callbacks.opaque, file_name, displayLevel, &mut info) };
|
||||||
error |= status;
|
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);
|
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]
|
#[test]
|
||||||
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
|
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
|
||||||
let cases = [
|
let cases = [
|
||||||
|
|||||||
Reference in New Issue
Block a user