Skip to content

Commit aac8dff

Browse files
committed
chore: development v0.3.37 - comprehensive testing complete [auto-commit]
1 parent 4cdbd72 commit aac8dff

39 files changed

+1506
-107
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ exclude = [
3636
# Workspace Package Metadata (inherited by all crates)
3737
# ─────────────────────────────────────────────────────────────────────────────
3838
[workspace.package]
39-
version = "0.3.34"
39+
version = "0.3.37"
4040
edition = "2024"
4141
rust-version = "1.85"
4242
license = "MPL-2.0 OR LicenseRef-UFFS-Commercial"

crates/uffs-cli/src/commands/json_helpers.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,3 @@ pub fn format_json_value(col: &uffs_polars::Column, row_idx: usize) -> String {
6565
Ok(value) => format_json_string(&value.to_string()),
6666
}
6767
}
68-

crates/uffs-cli/src/commands/output.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use uffs_core::{export_json, export_table};
1818
mod streaming;
1919
#[cfg(windows)]
2020
pub(crate) use streaming::StreamingWriter;
21-
#[cfg(windows)]
22-
pub(crate) use streaming::{format_json_string, format_json_value};
2321

24-
// For tests on non-Windows, we need the JSON helpers too
22+
// For tests, we need the JSON helpers - on Windows from streaming.rs, elsewhere from json_helpers.rs
23+
#[cfg(all(test, windows))]
24+
pub(super) use streaming::format_json_value;
2525
#[cfg(all(test, not(windows)))]
2626
#[path = "json_helpers.rs"]
2727
mod json_helpers;

crates/uffs-cli/src/commands/output_tests.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Tests for output helpers.
22
3+
use core::time::Duration;
34
use std::fs;
45
use std::path::PathBuf;
5-
use core::time::Duration;
66
use std::time::{SystemTime, UNIX_EPOCH};
77

88
use anyhow::Result;
@@ -463,4 +463,3 @@ fn test_cpp_footer_omits_fast_scan_message_when_elapsed_gt_1s() -> TestResult {
463463
assert_eq!(lines.get(footer_start + 3), Some(&""));
464464
Ok(())
465465
}
466-

crates/uffs-cli/src/commands/raw_io.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,25 @@ pub(super) struct NativeOfflineQueryResults {
3737
}
3838

3939
/// Query filter options for the search command.
40-
pub(crate) struct QueryFilters<'a> {
40+
pub struct QueryFilters<'a> {
4141
/// Parsed search pattern (glob, regex, or literal).
42-
pub(crate) parsed: &'a ParsedPattern,
42+
pub parsed: &'a ParsedPattern,
4343
/// Extension filter string (e.g., "pictures,mp4,pdf").
44-
pub(crate) ext_filter: Option<&'a str>,
44+
pub ext_filter: Option<&'a str>,
4545
/// Only return files (not directories).
46-
pub(crate) files_only: bool,
46+
pub files_only: bool,
4747
/// Only return directories (not files).
48-
pub(crate) dirs_only: bool,
48+
pub dirs_only: bool,
4949
/// Hide system files (files starting with $).
50-
pub(crate) hide_system: bool,
50+
pub hide_system: bool,
5151
/// Minimum file size filter.
52-
pub(crate) min_size: Option<u64>,
52+
pub min_size: Option<u64>,
5353
/// Maximum file size filter.
54-
pub(crate) max_size: Option<u64>,
54+
pub max_size: Option<u64>,
5555
/// Maximum number of results to return.
56-
pub(crate) limit: u32,
56+
pub limit: u32,
5757
}
5858

59-
60-
6159
/// Load and filter search data from a raw MFT file (cross-platform debugging).
6260
///
6361
/// This function loads a previously saved raw MFT file and processes it

crates/uffs-cli/src/commands/raw_io_windows.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,3 @@ pub(crate) async fn load_and_filter_data_index_multi(
327327

328328
Ok(final_result)
329329
}
330-

crates/uffs-cli/src/commands/streaming.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ impl<W: Write> StreamingWriter<W> {
108108
}
109109

110110
fn write_json_batch(&self, writer: &mut W, df: &uffs_mft::DataFrame) -> Result<usize> {
111-
use std::io::Write as _;
112-
113111
let col_names: Vec<_> = df.get_column_names();
114112
let columns: Vec<_> = col_names
115113
.iter()
@@ -229,4 +227,3 @@ pub(crate) fn format_json_value(col: &uffs_polars::Column, row_idx: usize) -> St
229227
Ok(value) => format_json_string(&value.to_string()),
230228
}
231229
}
232-

crates/uffs-diag/src/bin/compare_scan_parity.rs

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Comprehensive reference-output vs Rust scan parity comparison tool.
22
//!
3+
//! Exception: Standalone diagnostic CLI binary with complex parity output
4+
//! formatting. Not library code - splitting would reduce tool readability.
5+
//!
36
//! This tool performs deep comparison of UFFS scan outputs to verify that
47
//! the Rust implementation produces identical results to the reference output.
58
//!
@@ -69,17 +72,16 @@
6972
use core::sync::atomic::{AtomicUsize, Ordering};
7073
use std::collections::{HashMap, HashSet};
7174
use std::env;
72-
use std::path::Path;
73-
7475
use std::fs::File;
7576
use std::io::Write;
77+
use std::path::Path;
7678

7779
use anyhow::{Context, Result};
7880
use rayon::prelude::*;
7981
use uffs_diag::parity::{ComparisonResults, FieldStats};
80-
use uffs_polars::{CsvReadOptions, DataFrame, SerReader, StringChunked};
8182
// Wire in crate dependencies for version-locking
8283
use uffs_mft as _;
84+
use uffs_polars::{CsvReadOptions, DataFrame, SerReader, StringChunked};
8385

8486
// ============================================================================
8587
// Column Name Mappings (reference output <-> Rust)
@@ -635,23 +637,44 @@ fn print_results(results: &ComparisonResults) {
635637
println!(" Rust: {}", results.rust_file);
636638

637639
println!("\n📊 ROW COUNTS");
638-
println!(" Reference rows: {:>8}", format_num(results.reference_total_rows));
640+
println!(
641+
" Reference rows: {:>8}",
642+
format_num(results.reference_total_rows)
643+
);
639644
println!(" Rust rows: {:>12}", format_num(results.rust_total_rows));
640645
let diff = results.rust_total_rows as i64 - results.reference_total_rows as i64;
641646
println!(" Difference: {:>+12}", diff);
642647

643648
println!("\n🔗 PATH MATCHING");
644-
println!(" Common paths: {:>12}", format_num(results.common_paths));
645-
println!(" Reference only: {:>12}", format_num(results.reference_only_paths));
646-
println!(" Rust only: {:>12}", format_num(results.rust_only_paths));
649+
println!(
650+
" Common paths: {:>12}",
651+
format_num(results.common_paths)
652+
);
653+
println!(
654+
" Reference only: {:>12}",
655+
format_num(results.reference_only_paths)
656+
);
657+
println!(
658+
" Rust only: {:>12}",
659+
format_num(results.rust_only_paths)
660+
);
647661
println!(" Match rate: {:>11.4}%", results.path_match_rate);
648662

649663
println!("\n📎 ALTERNATE DATA STREAMS (ADS)");
650-
println!(" Reference ADS: {:>10}", format_num(results.reference_ads_count));
651-
println!(" Rust ADS entries: {:>10}", format_num(results.rust_ads_count));
664+
println!(
665+
" Reference ADS: {:>10}",
666+
format_num(results.reference_ads_count)
667+
);
668+
println!(
669+
" Rust ADS entries: {:>10}",
670+
format_num(results.rust_ads_count)
671+
);
652672

653673
println!("\n📈 FIELD-BY-FIELD COMPARISON");
654-
println!("{:>20} {:>12} {:>12} {:>10} {:>12}", "Field", "Compared", "Matches", "Rate", "Max Diff");
674+
println!(
675+
"{:>20} {:>12} {:>12} {:>10} {:>12}",
676+
"Field", "Compared", "Matches", "Rate", "Max Diff"
677+
);
655678
println!("{}", "-".repeat(70));
656679

657680
let mut fields: Vec<_> = results.field_stats.keys().collect();
@@ -666,7 +689,11 @@ fn print_results(results: &ComparisonResults) {
666689
format_num(stats.total_compared as usize),
667690
format_num(stats.exact_matches as usize),
668691
stats.match_rate(),
669-
if stats.max_abs_diff > 0.0 { format!("{:.0}", stats.max_abs_diff) } else { "-".to_string() }
692+
if stats.max_abs_diff > 0.0 {
693+
format!("{:.0}", stats.max_abs_diff)
694+
} else {
695+
"-".to_string()
696+
}
670697
);
671698
}
672699
}
@@ -714,7 +741,10 @@ fn print_results(results: &ComparisonResults) {
714741
} else {
715742
println!("\n⚠️ DIFFERENCES DETECTED:");
716743
if results.reference_only_paths > 0 {
717-
println!(" - {} paths missing from Rust", results.reference_only_paths);
744+
println!(
745+
" - {} paths missing from Rust",
746+
results.reference_only_paths
747+
);
718748
}
719749
if results.rust_only_paths > 0 {
720750
println!(" - {} extra paths in Rust", results.rust_only_paths);
@@ -733,7 +763,11 @@ fn write_markdown_report(results: &ComparisonResults, path: &Path) -> Result<()>
733763

734764
writeln!(f, "# UFFS Scan Parity Report")?;
735765
writeln!(f)?;
736-
writeln!(f, "Generated: {}", chrono::Local::now().format("%Y-%m-%d %H:%M:%S"))?;
766+
writeln!(
767+
f,
768+
"Generated: {}",
769+
chrono::Local::now().format("%Y-%m-%d %H:%M:%S")
770+
)?;
737771
writeln!(f)?;
738772

739773
writeln!(f, "## Files Compared")?;
@@ -748,7 +782,11 @@ fn write_markdown_report(results: &ComparisonResults, path: &Path) -> Result<()>
748782
writeln!(f)?;
749783
writeln!(f, "| Metric | Count |")?;
750784
writeln!(f, "|--------|------:|")?;
751-
writeln!(f, "| Reference rows | {} |", format_num(results.reference_total_rows))?;
785+
writeln!(
786+
f,
787+
"| Reference rows | {} |",
788+
format_num(results.reference_total_rows)
789+
)?;
752790
writeln!(f, "| Rust rows | {} |", format_num(results.rust_total_rows))?;
753791
let diff = results.rust_total_rows as i64 - results.reference_total_rows as i64;
754792
writeln!(f, "| Difference | {:+} |", diff)?;
@@ -759,16 +797,28 @@ fn write_markdown_report(results: &ComparisonResults, path: &Path) -> Result<()>
759797
writeln!(f, "| Metric | Count |")?;
760798
writeln!(f, "|--------|------:|")?;
761799
writeln!(f, "| Common paths | {} |", format_num(results.common_paths))?;
762-
writeln!(f, "| Reference only | {} |", format_num(results.reference_only_paths))?;
800+
writeln!(
801+
f,
802+
"| Reference only | {} |",
803+
format_num(results.reference_only_paths)
804+
)?;
763805
writeln!(f, "| Rust only | {} |", format_num(results.rust_only_paths))?;
764-
writeln!(f, "| **Match rate** | **{:.4}%** |", results.path_match_rate)?;
806+
writeln!(
807+
f,
808+
"| **Match rate** | **{:.4}%** |",
809+
results.path_match_rate
810+
)?;
765811
writeln!(f)?;
766812

767813
writeln!(f, "## Alternate Data Streams (ADS)")?;
768814
writeln!(f)?;
769815
writeln!(f, "| Source | ADS Count |")?;
770816
writeln!(f, "|--------|----------:|")?;
771-
writeln!(f, "| Reference | {} |", format_num(results.reference_ads_count))?;
817+
writeln!(
818+
f,
819+
"| Reference | {} |",
820+
format_num(results.reference_ads_count)
821+
)?;
772822
writeln!(f, "| Rust | {} |", format_num(results.rust_ads_count))?;
773823
writeln!(f)?;
774824

@@ -790,7 +840,11 @@ fn write_markdown_report(results: &ComparisonResults, path: &Path) -> Result<()>
790840
format_num(stats.total_compared as usize),
791841
format_num(stats.exact_matches as usize),
792842
stats.match_rate(),
793-
if stats.max_abs_diff > 0.0 { format!("{:.0}", stats.max_abs_diff) } else { "-".to_string() }
843+
if stats.max_abs_diff > 0.0 {
844+
format!("{:.0}", stats.max_abs_diff)
845+
} else {
846+
"-".to_string()
847+
}
794848
)?;
795849
}
796850
}
@@ -803,12 +857,19 @@ fn write_markdown_report(results: &ComparisonResults, path: &Path) -> Result<()>
803857
writeln!(f, "## Summary")?;
804858
writeln!(f)?;
805859
if all_match {
806-
writeln!(f, "✅ **PERFECT PARITY** - All paths and fields match exactly!")?;
860+
writeln!(
861+
f,
862+
"✅ **PERFECT PARITY** - All paths and fields match exactly!"
863+
)?;
807864
} else {
808865
writeln!(f, "⚠️ **DIFFERENCES DETECTED**")?;
809866
writeln!(f)?;
810867
if results.reference_only_paths > 0 {
811-
writeln!(f, "- {} paths missing from Rust", results.reference_only_paths)?;
868+
writeln!(
869+
f,
870+
"- {} paths missing from Rust",
871+
results.reference_only_paths
872+
)?;
812873
}
813874
if results.rust_only_paths > 0 {
814875
writeln!(f, "- {} extra paths in Rust", results.rust_only_paths)?;

crates/uffs-diag/src/parity/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@
66
mod stats;
77

88
pub use stats::{ComparisonResults, FieldStats};
9-

crates/uffs-diag/src/parity/stats.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ impl FieldStats {
4949
}
5050

5151
/// Merge another `FieldStats` into this one.
52-
#[expect(clippy::float_arithmetic, reason = "statistics require accumulating f64 sums")]
52+
#[expect(
53+
clippy::float_arithmetic,
54+
reason = "statistics require accumulating f64 sums"
55+
)]
5356
pub fn merge(&mut self, other: Self) {
5457
self.total_compared += other.total_compared;
5558
self.exact_matches += other.exact_matches;
@@ -97,4 +100,3 @@ pub struct ComparisonResults {
97100
/// Sample paths only in Rust.
98101
pub sample_rust_only: Vec<String>,
99102
}
100-

0 commit comments

Comments
 (0)