refactor(cli): move compression metadata policy to Rust

Keep the private stat_t probe, destination opening, metadata syscalls, and format callbacks in C, but route the regular-source plus stdin/stdout exception policy through the Rust fileio preference layer. The Rust ABI bridge normalizes the scalar consumed by the existing destination lifecycle, with compile-time value assertions and focused tests covering regular, non-regular, stdin, stdout, and nonzero scalar inputs.

Test Plan: Not run by request; cargo, make, native tests, and heavy commands were intentionally avoided. Lightweight git diff --check passed.
This commit is contained in:
2026-07-21 08:34:04 +02:00
parent df30cb58d4
commit e01f79fb1a
2 changed files with 87 additions and 6 deletions
+68
View File
@@ -48,7 +48,14 @@ pub const FIO_RUST_REMOVE_FILE_ACTION_STAT_FAILED: c_int = 1;
pub const FIO_RUST_REMOVE_FILE_ACTION_NON_REGULAR: c_int = 2;
pub const FIO_RUST_REMOVE_FILE_ACTION_FAILED: c_int = 3;
pub const FIO_RUST_REMOVE_FILE_ACTION_INVALID: c_int = 4;
const FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO: c_int = 0;
const FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES: c_int = 1;
const UTIL_FILESIZE_UNKNOWN: u64 = u64::MAX;
const _: () = {
assert!(FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO == 0);
assert!(FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES == 1);
};
const COMPRESSED_FILE_EXTENSIONS: &[&[u8]] = &[
b".zst",
b".tzst",
@@ -764,6 +771,37 @@ pub extern "C" fn FIO_rust_removeFileAction(status: c_int) -> c_int {
remove_file_action(status)
}
#[inline]
fn compress_destination_transfer_stat(
source_is_stdin: c_int,
destination_is_stdout: c_int,
source_is_regular: c_int,
) -> c_int {
if source_is_stdin != 0 || destination_is_stdout != 0 {
FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO
} else {
c_int::from(source_is_regular != 0)
}
}
/// Select whether compression should transfer source metadata to its output.
///
/// C retains the private `stat_t` probe and the actual metadata operations.
/// Rust owns the scalar policy: stdin and stdout never transfer metadata, and
/// otherwise a regular source enables the transfer.
#[no_mangle]
pub extern "C" fn FIO_rust_compressDestinationTransferStat(
source_is_stdin: c_int,
destination_is_stdout: c_int,
source_is_regular: c_int,
) -> c_int {
compress_destination_transfer_stat(
source_is_stdin,
destination_is_stdout,
source_is_regular,
)
}
/// Callback projection for the C-owned `--list` file operations.
#[repr(C)]
pub struct FIO_listMultipleFilesCallbacks_t {
@@ -2677,6 +2715,36 @@ mod tests {
}
}
#[test]
fn compression_destination_transfer_stat_preserves_metadata_exceptions() {
for (source_is_stdin, destination_is_stdout, source_is_regular, expected) in [
(0, 0, 0, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO),
(0, 0, 1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES),
(-1, 0, 1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO),
(0, 1, 1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO),
(0, 0, -1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES),
] {
assert_eq!(
compress_destination_transfer_stat(
source_is_stdin,
destination_is_stdout,
source_is_regular,
),
expected,
"unexpected metadata policy for stdin={source_is_stdin}, stdout={destination_is_stdout}, regular={source_is_regular}"
);
assert_eq!(
FIO_rust_compressDestinationTransferStat(
source_is_stdin,
destination_is_stdout,
source_is_regular,
),
expected,
"C ABI disagrees for stdin={source_is_stdin}, stdout={destination_is_stdout}, regular={source_is_regular}"
);
}
}
#[test]
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
let cases = [