From 8e241eaa28a77e2c185d45289f7b2d5722c54684 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Mon, 20 Jul 2026 13:37:00 +0200 Subject: [PATCH] refactor(cli): move --list stdin predicate to Rust The --list stdin callback was a stateless string predicate: it ignored its opaque context and compared the input name with the fixed stdin marker. Move that callback under its existing caller symbol into the Rust CLI archive, so C no longer owns this policy leaf. The Rust implementation preserves the callback ABI and returns the same 1/0 result for the marker and ordinary names. File opening, frame parsing, diagnostics, human-readable formatting, private file-info storage, and list orchestration remain C-owned. The optional codec-version helpers remain untouched because their build-time library configuration is not propagated to the Rust archive. Test Plan: - `clang -fsyntax-only -Iprograms -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dictBuilder programs/fileio.c` -- passed. - `rustfmt --edition 2021 --check --config skip_children=true rust/cli/src/lib.rs` -- passed. - `git diff --check` and `git diff --cached --check` -- passed. - Cargo, clippy, native builds, and upstream tests were not run per the explicit no-heavy-command constraint. --- programs/fileio.c | 8 ++------ rust/cli/src/lib.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 7a6af7929..46a842f6a 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -4998,12 +4998,8 @@ FIO_listFile(const char* inFileName, int displayLevel, } } -static int -FIO_listFileIsStdin(void* opaque, const char* fileName) -{ - (void)opaque; - return !strcmp(fileName, stdinmark); -} +/* Rust owns this stateless --list input-name predicate. */ +int FIO_listFileIsStdin(void* opaque, const char* fileName); static void FIO_listFileDisplayStdinError(void* opaque) diff --git a/rust/cli/src/lib.rs b/rust/cli/src/lib.rs index 31c5da2a3..0a2631e39 100644 --- a/rust/cli/src/lib.rs +++ b/rust/cli/src/lib.rs @@ -29,3 +29,41 @@ mod zstd_cli; #[cfg(feature = "cli")] #[path = "../../src/zstdcli_trace.rs"] mod zstdcli_trace; + +#[cfg(feature = "cli")] +use std::ffi::c_void; +#[cfg(feature = "cli")] +use std::os::raw::{c_char, c_int}; + +/// Match the C `--list` stdin callback without crossing any file-I/O state. +#[cfg(feature = "cli")] +#[no_mangle] +pub unsafe extern "C" fn FIO_listFileIsStdin( + _opaque: *mut c_void, + file_name: *const c_char, +) -> c_int { + assert!(!file_name.is_null()); + c_int::from(unsafe { libc::strcmp(file_name, c"/*stdin*\\".as_ptr()) == 0 }) +} + +#[cfg(all(test, feature = "cli"))] +mod tests { + use super::FIO_listFileIsStdin; + use std::ffi::CString; + use std::ptr; + + #[test] + fn list_stdin_callback_matches_only_the_stdin_marker() { + let stdin_name = CString::new("/*stdin*\\").unwrap(); + let ordinary_name = CString::new("input.zst").unwrap(); + + assert_eq!( + unsafe { FIO_listFileIsStdin(ptr::null_mut(), stdin_name.as_ptr()) }, + 1 + ); + assert_eq!( + unsafe { FIO_listFileIsStdin(ptr::null_mut(), ordinary_name.as_ptr()) }, + 0 + ); + } +}