1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{
args::Fraction,
data_tree::DataTree,
fs_tree_builder::FsTreeBuilder,
os_string_display::OsStringDisplay,
reporter::ParallelReporter,
runtime_error::RuntimeError,
size::Size,
status_board::GLOBAL_STATUS_BOARD,
visualizer::{ColumnWidthDistribution, Direction, Visualizer},
};
use std::{fs::Metadata, iter::once, num::NonZeroUsize, path::PathBuf};
pub struct Sub<Data, GetData, Report>
where
Data: Size + Into<u64> + Send + Sync,
Report: ParallelReporter<Data> + Sync,
GetData: Fn(&Metadata) -> Data + Copy + Sync,
{
pub files: Vec<PathBuf>,
pub bytes_format: Data::DisplayFormat,
pub direction: Direction,
pub column_width_distribution: ColumnWidthDistribution,
pub max_depth: NonZeroUsize,
pub get_data: GetData,
pub reporter: Report,
pub min_ratio: Fraction,
pub no_sort: bool,
}
impl<Data, GetData, Report> Sub<Data, GetData, Report>
where
Data: Size + Into<u64> + Send + Sync,
Report: ParallelReporter<Data> + Sync,
GetData: Fn(&Metadata) -> Data + Copy + Sync,
{
pub fn run(self) -> Result<(), RuntimeError> {
let Sub {
files,
bytes_format,
direction,
column_width_distribution,
max_depth,
get_data,
reporter,
min_ratio,
no_sort,
} = self;
let mut iter = files
.into_iter()
.map(|root| -> DataTree<OsStringDisplay, Data> {
FsTreeBuilder {
reporter: &reporter,
root,
get_data,
}
.into()
});
let data_tree = if let Some(data_tree) = iter.next() {
data_tree
} else {
return Sub {
files: vec![".".into()],
reporter,
..self
}
.run();
};
let data_tree = if iter.len() == 0 {
data_tree
} else {
let children: Vec<_> = once(data_tree).chain(iter).collect();
DataTree::dir(
OsStringDisplay::os_string_from("(total)"),
Data::default(),
children,
)
};
if reporter.destroy().is_err() {
eprintln!("[warning] Failed to destroy the thread that reports progress");
}
let min_ratio: f32 = min_ratio.into();
let data_tree = {
let mut data_tree = data_tree;
if min_ratio > 0.0 {
data_tree.par_cull_insignificant_data(min_ratio);
}
if !no_sort {
data_tree.par_sort_by(|left, right| left.data().cmp(&right.data()).reverse());
}
data_tree
};
let visualizer = Visualizer {
data_tree: &data_tree,
bytes_format,
direction,
column_width_distribution,
max_depth,
};
GLOBAL_STATUS_BOARD.clear_line(0);
print!("{}", visualizer);
Ok(())
}
}