refactor(cli): move --list multi-file policy to Rust
Move stdin and empty-input validation, header selection, per-file iteration, status aggregation, and multi-file total selection into the Rust CLI policy layer. The callback projection keeps C responsible for its private file-info storage, file parsing, diagnostics, human-readable formatting, and per-file listing. Only successful and frame-error records contribute to the aggregate, matching the original early-return behavior for invalid or truncated inputs. Test Plan: - `rustfmt --edition 2021 --check rust/src/fileio_prefs.rs` -- passed. - `git diff --cached --check` -- passed. - Cargo, native, and full test commands were not run per the explicit no-heavy-command constraint.
This commit is contained in:
+114
-60
@@ -4544,15 +4544,6 @@ typedef char FIO_rust_file_info_size[
|
||||
? 7 * sizeof(U64)
|
||||
: 13 * sizeof(U32))) ? 1 : -1];
|
||||
|
||||
void FIO_rust_addFInfo(fileInfo_t* output, fileInfo_t const* fi1, fileInfo_t const* fi2);
|
||||
|
||||
static fileInfo_t FIO_addFInfo(fileInfo_t fi1, fileInfo_t fi2)
|
||||
{
|
||||
fileInfo_t total;
|
||||
FIO_rust_addFInfo(&total, &fi1, &fi2);
|
||||
return total;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
info_success=0,
|
||||
info_frame_error=1,
|
||||
@@ -4561,6 +4552,35 @@ typedef enum {
|
||||
info_truncated_input=4
|
||||
} InfoError;
|
||||
|
||||
/* 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
|
||||
* after FIO_listFile has finished its C-owned open/parse/display work. */
|
||||
typedef struct {
|
||||
U64 decompressedSize;
|
||||
U64 compressedSize;
|
||||
int numActualFrames;
|
||||
int numSkippableFrames;
|
||||
int decompUnavailable;
|
||||
int usesCheck;
|
||||
U32 nbFiles;
|
||||
} FIO_listFileInfoProjection_t;
|
||||
|
||||
typedef struct {
|
||||
void* opaque;
|
||||
int (*isStdin)(void* opaque, const char* fileName);
|
||||
void (*displayStdinError)(void* opaque);
|
||||
void (*displayNoFilesError)(void* opaque);
|
||||
void (*displayHeader)(void* opaque);
|
||||
int (*listFile)(void* opaque, const char* fileName, int displayLevel,
|
||||
FIO_listFileInfoProjection_t* info);
|
||||
void (*displayTotal)(void* opaque,
|
||||
const FIO_listFileInfoProjection_t* total);
|
||||
} FIO_listMultipleFilesCallbacks_t;
|
||||
|
||||
int FIO_rust_listMultipleFiles(unsigned numFiles, const char** filenameTable,
|
||||
int displayLevel,
|
||||
const FIO_listMultipleFilesCallbacks_t* callbacks);
|
||||
|
||||
enum {
|
||||
FIO_RUST_ANALYZE_DIAG_SEEKED_PAST_FILE = 0,
|
||||
FIO_RUST_ANALYZE_DIAG_INCOMPLETE_FRAME = 1,
|
||||
@@ -4733,7 +4753,8 @@ displayInfo(const char* inFileName, const fileInfo_t* info, int displayLevel)
|
||||
}
|
||||
|
||||
static int
|
||||
FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel)
|
||||
FIO_listFile(const char* inFileName, int displayLevel,
|
||||
FIO_listFileInfoProjection_t* output)
|
||||
{
|
||||
fileInfo_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
@@ -4761,63 +4782,96 @@ FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel)
|
||||
}
|
||||
|
||||
displayInfo(inFileName, &info, displayLevel);
|
||||
*total = FIO_addFInfo(*total, info);
|
||||
output->decompressedSize = info.decompressedSize;
|
||||
output->compressedSize = info.compressedSize;
|
||||
output->numActualFrames = info.numActualFrames;
|
||||
output->numSkippableFrames = info.numSkippableFrames;
|
||||
output->decompUnavailable = info.decompUnavailable;
|
||||
output->usesCheck = info.usesCheck;
|
||||
output->nbFiles = info.nbFiles;
|
||||
assert(error == info_success || error == info_frame_error);
|
||||
return (int)error;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
FIO_listFileIsStdin(void* opaque, const char* fileName)
|
||||
{
|
||||
(void)opaque;
|
||||
return !strcmp(fileName, stdinmark);
|
||||
}
|
||||
|
||||
static void
|
||||
FIO_listFileDisplayStdinError(void* opaque)
|
||||
{
|
||||
(void)opaque;
|
||||
DISPLAYLEVEL(1, "zstd: --list does not support reading from standard input");
|
||||
DISPLAYLEVEL(1, " \n");
|
||||
}
|
||||
|
||||
static void
|
||||
FIO_listFileDisplayNoFilesError(void* opaque)
|
||||
{
|
||||
(void)opaque;
|
||||
if (!UTIL_isConsole(stdin)) {
|
||||
DISPLAYLEVEL(1, "zstd: --list does not support reading from standard input \n");
|
||||
}
|
||||
DISPLAYLEVEL(1, "No files given \n");
|
||||
}
|
||||
|
||||
static void
|
||||
FIO_listFileDisplayHeader(void* opaque)
|
||||
{
|
||||
(void)opaque;
|
||||
DISPLAYOUT("Frames Skips Compressed Uncompressed Ratio Check Filename\n");
|
||||
}
|
||||
|
||||
static int
|
||||
FIO_listFileCallback(void* opaque, const char* fileName, int displayLevel,
|
||||
FIO_listFileInfoProjection_t* info)
|
||||
{
|
||||
(void)opaque;
|
||||
memset(info, 0, sizeof(*info));
|
||||
return FIO_listFile(fileName, displayLevel, info);
|
||||
}
|
||||
|
||||
static void
|
||||
FIO_listFileDisplayTotal(void* opaque,
|
||||
const FIO_listFileInfoProjection_t* total)
|
||||
{
|
||||
UTIL_HumanReadableSize_t const compressed_hrs = UTIL_makeHumanReadableSize(total->compressedSize);
|
||||
UTIL_HumanReadableSize_t const decompressed_hrs = UTIL_makeHumanReadableSize(total->decompressedSize);
|
||||
double const ratio = (total->compressedSize == 0) ? 0 : ((double)total->decompressedSize)/(double)total->compressedSize;
|
||||
const char* const checkString = (total->usesCheck ? "XXH64" : "");
|
||||
(void)opaque;
|
||||
DISPLAYOUT("----------------------------------------------------------------- \n");
|
||||
if (total->decompUnavailable) {
|
||||
DISPLAYOUT("%6d %5d %6.*f%4s %5s %u files\n",
|
||||
total->numSkippableFrames + total->numActualFrames,
|
||||
total->numSkippableFrames,
|
||||
compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
|
||||
checkString, (unsigned)total->nbFiles);
|
||||
} else {
|
||||
DISPLAYOUT("%6d %5d %6.*f%4s %8.*f%4s %5.3f %5s %u files\n",
|
||||
total->numSkippableFrames + total->numActualFrames,
|
||||
total->numSkippableFrames,
|
||||
compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
|
||||
decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,
|
||||
ratio, checkString, (unsigned)total->nbFiles);
|
||||
}
|
||||
}
|
||||
|
||||
int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel)
|
||||
{
|
||||
/* ensure no specified input is stdin (needs fseek() capability) */
|
||||
{ unsigned u;
|
||||
for (u=0; u<numFiles;u++) {
|
||||
ERROR_IF(!strcmp (filenameTable[u], stdinmark),
|
||||
1, "zstd: --list does not support reading from standard input");
|
||||
} }
|
||||
|
||||
if (numFiles == 0) {
|
||||
if (!UTIL_isConsole(stdin)) {
|
||||
DISPLAYLEVEL(1, "zstd: --list does not support reading from standard input \n");
|
||||
}
|
||||
DISPLAYLEVEL(1, "No files given \n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (displayLevel <= 2) {
|
||||
DISPLAYOUT("Frames Skips Compressed Uncompressed Ratio Check Filename\n");
|
||||
}
|
||||
{ int error = 0;
|
||||
fileInfo_t total;
|
||||
memset(&total, 0, sizeof(total));
|
||||
total.usesCheck = 1;
|
||||
/* --list each file, and check for any error */
|
||||
{ unsigned u;
|
||||
for (u=0; u<numFiles;u++) {
|
||||
error |= FIO_listFile(&total, filenameTable[u], displayLevel);
|
||||
} }
|
||||
if (numFiles > 1 && displayLevel <= 2) { /* display total */
|
||||
UTIL_HumanReadableSize_t const compressed_hrs = UTIL_makeHumanReadableSize(total.compressedSize);
|
||||
UTIL_HumanReadableSize_t const decompressed_hrs = UTIL_makeHumanReadableSize(total.decompressedSize);
|
||||
double const ratio = (total.compressedSize == 0) ? 0 : ((double)total.decompressedSize)/(double)total.compressedSize;
|
||||
const char* const checkString = (total.usesCheck ? "XXH64" : "");
|
||||
DISPLAYOUT("----------------------------------------------------------------- \n");
|
||||
if (total.decompUnavailable) {
|
||||
DISPLAYOUT("%6d %5d %6.*f%4s %5s %u files\n",
|
||||
total.numSkippableFrames + total.numActualFrames,
|
||||
total.numSkippableFrames,
|
||||
compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
|
||||
checkString, (unsigned)total.nbFiles);
|
||||
} else {
|
||||
DISPLAYOUT("%6d %5d %6.*f%4s %8.*f%4s %5.3f %5s %u files\n",
|
||||
total.numSkippableFrames + total.numActualFrames,
|
||||
total.numSkippableFrames,
|
||||
compressed_hrs.precision, compressed_hrs.value, compressed_hrs.suffix,
|
||||
decompressed_hrs.precision, decompressed_hrs.value, decompressed_hrs.suffix,
|
||||
ratio, checkString, (unsigned)total.nbFiles);
|
||||
} }
|
||||
return error;
|
||||
}
|
||||
FIO_listMultipleFilesCallbacks_t callbacks;
|
||||
callbacks.opaque = NULL;
|
||||
callbacks.isStdin = FIO_listFileIsStdin;
|
||||
callbacks.displayStdinError = FIO_listFileDisplayStdinError;
|
||||
callbacks.displayNoFilesError = FIO_listFileDisplayNoFilesError;
|
||||
callbacks.displayHeader = FIO_listFileDisplayHeader;
|
||||
callbacks.listFile = FIO_listFileCallback;
|
||||
callbacks.displayTotal = FIO_listFileDisplayTotal;
|
||||
return FIO_rust_listMultipleFiles(numFiles, filenameTable, displayLevel, &callbacks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user