Skip to main content

diskr/analyzer/
size.rs

1use crate::scanner::FsNode;
2use serde::Serialize;
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Serialize)]
6pub struct SizeEntry {
7    pub path: PathBuf,
8    pub size: u64,
9    pub is_dir: bool,
10}
11
12pub fn top_files(root: &FsNode, min_size: u64, limit: usize) -> Vec<SizeEntry> {
13    let mut files = Vec::new();
14    root.flatten_files(&mut files);
15    let mut entries: Vec<SizeEntry> = files.into_iter()
16        .filter(|f| f.size >= min_size)
17        .map(|f| SizeEntry { path: f.path.clone(), size: f.size, is_dir: false })
18        .collect();
19    entries.sort_by(|a, b| b.size.cmp(&a.size));
20    entries.truncate(limit);
21    entries
22}
23
24pub fn top_dirs(root: &FsNode, limit: usize) -> Vec<SizeEntry> {
25    let mut out = Vec::new();
26    collect_dirs(root, &mut out);
27    out.sort_by(|a, b| b.size.cmp(&a.size));
28    out.truncate(limit);
29    out
30}
31
32fn collect_dirs(node: &FsNode, out: &mut Vec<SizeEntry>) {
33    if !node.is_dir { return; }
34    out.push(SizeEntry { path: node.path.clone(), size: node.size, is_dir: true });
35    for c in &node.children {
36        if c.is_dir { collect_dirs(c, out); }
37    }
38}
39
40pub fn type_breakdown(root: &FsNode) -> Vec<(String, u64, u64)> {
41    let mut files = Vec::new();
42    root.flatten_files(&mut files);
43    use std::collections::HashMap;
44    let mut groups: HashMap<&'static str, (u64, u64)> = HashMap::new();
45    for f in files {
46        let ext = f.path.extension().and_then(|e| e.to_str()).unwrap_or("").to_lowercase();
47        let cat = categorize_ext(&ext);
48        let entry = groups.entry(cat).or_insert((0, 0));
49        entry.0 += f.size;
50        entry.1 += 1;
51    }
52    let mut result: Vec<(String, u64, u64)> = groups.into_iter().map(|(k, (s, c))| (k.to_string(), s, c)).collect();
53    result.sort_by(|a, b| b.1.cmp(&a.1));
54    result
55}
56
57fn categorize_ext(ext: &str) -> &'static str {
58    match ext {
59        "mp4" | "mkv" | "avi" | "mov" | "webm" | "flv" => "video",
60        "jpg" | "jpeg" | "png" | "gif" | "webp" | "bmp" | "svg" | "raw" => "image",
61        "mp3" | "wav" | "flac" | "ogg" | "m4a" => "audio",
62        "zip" | "tar" | "gz" | "xz" | "7z" | "rar" | "bz2" | "zst" => "archive",
63        "iso" | "img" | "appimage" | "deb" | "rpm" => "package",
64        "pdf" | "doc" | "docx" | "xls" | "xlsx" | "ppt" | "pptx" | "odt" => "document",
65        "log" => "log",
66        "so" | "dll" | "bin" | "exe" | "o" | "a" => "binary",
67        "" => "no-extension",
68        _ => "other",
69    }
70}