Filesystem summary
Aggregate file sizes, counts, and directory depth in one pass.
The heap is a structured Summary — multiple metrics accumulated
simultaneously.
#![allow(unused)]
fn main() {
//! Filesystem tree summary — structured heap accumulating multiple metrics.
#[cfg(test)]
mod tests {
use hylic::prelude::*;
use insta::assert_snapshot;
/// A filesystem entry: either a file (leaf) or a directory (branch).
#[derive(Clone)]
#[allow(dead_code)]
enum FsEntry {
File { name: String, size: u64 },
Dir { name: String, children: Vec<FsEntry> },
}
impl FsEntry {
fn file(name: &str, size: u64) -> Self {
FsEntry::File { name: name.into(), size }
}
fn dir(name: &str, ch: Vec<FsEntry>) -> Self {
FsEntry::Dir { name: name.into(), children: ch }
}
}
/// Accumulates size, file count, and directory count in one pass.
#[derive(Clone, Debug, PartialEq)]
struct Summary {
total_size: u64,
file_count: usize,
dir_count: usize,
}
#[test]
fn summarize_filesystem() {
let tree = FsEntry::dir("project", vec![
FsEntry::file("README.md", 1200),
FsEntry::dir("src", vec![
FsEntry::file("main.rs", 5000),
FsEntry::file("lib.rs", 3000),
FsEntry::dir("utils", vec![
FsEntry::file("helpers.rs", 800),
]),
]),
FsEntry::file("Cargo.toml", 400),
]);
// Files are implicit leaves; only directories produce children.
let graph: Treeish<FsEntry> = treeish_visit(|entry: &FsEntry, cb: &mut dyn FnMut(&FsEntry)| {
if let FsEntry::Dir { children, .. } = entry {
for child in children { cb(child); }
}
});
// Structured heap — multiple metrics tracked in one pass. H = R = Summary.
let summarize: Fold<FsEntry, Summary, Summary> = fold(
|entry: &FsEntry| match entry {
FsEntry::File { size, .. } =>
Summary { total_size: *size, file_count: 1, dir_count: 0 },
FsEntry::Dir { .. } =>
Summary { total_size: 0, file_count: 0, dir_count: 1 },
},
|heap: &mut Summary, child: &Summary| {
heap.total_size += child.total_size;
heap.file_count += child.file_count;
heap.dir_count += child.dir_count;
},
|h: &Summary| h.clone(),
);
let result: Summary = FUSED.run(&summarize, &graph, &tree);
assert_eq!(result, Summary {
total_size: 10400, file_count: 5, dir_count: 3,
});
assert_snapshot!("fs_summary", format!(
"project/: {} bytes, {} files, {} dirs",
result.total_size, result.file_count, result.dir_count,
));
}
}
}
Output:
project/: 10400 bytes, 5 files, 3 dirs