parallel_disk_usage/visualizer/methods/
initial_table.rs1use super::{NodeInfo, Table, BORDER_COLUMNS, PERCENTAGE_COLUMN_MAX_WIDTH};
2use crate::{data_tree::DataTree, size, visualizer::Visualizer};
3use assert_cmp::debug_assert_op;
4use derive_more::{Deref, DerefMut};
5use std::{cmp::max, fmt::Display, num::NonZeroUsize};
6
7#[derive(Deref, DerefMut)]
8pub(super) struct InitialRow<Name, NodeData> {
9 #[deref]
10 #[deref_mut]
11 pub(super) node_info: NodeInfo<Name, NodeData>,
12 pub(super) ancestors: Vec<NodeInfo<Name, NodeData>>,
13 pub(super) preceding_sibling: Option<NodeInfo<Name, NodeData>>,
14 pub(super) size: String,
15 pub(super) percentage: String,
16}
17
18impl<Name, NodeData> InitialRow<Name, NodeData> {
19 #[inline]
20 pub(super) fn parent(&self) -> Option<&'_ NodeInfo<Name, NodeData>> {
21 self.ancestors.last()
22 }
23}
24
25#[derive(Default, Clone, Copy)]
26pub(super) struct InitialColumnWidth {
27 pub(super) size_column_width: usize,
28}
29
30impl InitialColumnWidth {
31 #[inline]
32 pub(super) const fn total_max_width(self) -> usize {
33 self.size_column_width + PERCENTAGE_COLUMN_MAX_WIDTH + BORDER_COLUMNS
34 }
35}
36
37pub(super) type InitialTable<Name, NodeData> =
38 Table<InitialRow<Name, NodeData>, InitialColumnWidth>;
39
40pub(super) fn render_initial<Name, Size>(
41 visualizer: Visualizer<Name, Size>,
42) -> InitialTable<&'_ Name, Size>
43where
44 Name: Display,
45 Size: size::Size + Into<u64>,
46{
47 #[derive(Clone)]
48 struct Param<Name, NodeData> {
49 index_as_child: usize,
50 ancestors: Vec<NodeInfo<Name, NodeData>>,
51 preceding_sibling: Option<NodeInfo<Name, NodeData>>,
52 }
53
54 struct ActResult<Name, NodeData> {
55 node_info: NodeInfo<Name, NodeData>,
56 }
57
58 struct TraverseResult<Name, NodeData> {
59 node_info: NodeInfo<Name, NodeData>,
60 }
61
62 fn traverse<'a, Name, Size, Act>(
63 tree: &'a DataTree<Name, Size>,
64 act: &mut Act,
65 param: Param<&'a Name, Size>,
66 ) -> Option<TraverseResult<&'a Name, Size>>
67 where
68 Size: size::Size,
69 Act: FnMut(&'a DataTree<Name, Size>, Param<&'a Name, Size>) -> ActResult<&'a Name, Size>,
70 {
71 let ActResult { node_info } = act(tree, param.clone());
72 let mut preceding_sibling = None;
73 for (index_as_child, child) in tree.children().iter().enumerate() {
74 let mut ancestors = Vec::with_capacity(param.ancestors.len() + 1);
75 ancestors.clone_from(¶m.ancestors);
76 ancestors.push(node_info);
77 let traverse_result = traverse(
78 child,
79 act,
80 Param {
81 index_as_child,
82 ancestors,
83 preceding_sibling,
84 },
85 );
86 preceding_sibling = traverse_result.map(|x| x.node_info);
87 }
88 Some(TraverseResult { node_info })
89 }
90
91 let mut initial_table = InitialTable::default();
92 let total_fs_size = visualizer.data_tree.size().into();
93
94 traverse(
95 visualizer.data_tree,
96 &mut |node, param| {
97 let Param {
98 index_as_child,
99 ancestors,
100 preceding_sibling,
101 } = param;
102 let name = node.name();
103 let node_data = node.size();
104 let row_index = initial_table.len();
105 let children_count = node.children().len();
106 let fs_size = node.size().into();
107 let percentage = if total_fs_size == 0 {
108 "0%".to_string()
109 } else {
110 let percentage = rounded_div::u64(fs_size * 100, total_fs_size);
111 format!("{percentage}%")
112 };
113 let size = node.size().display(visualizer.bytes_format).to_string();
114 let sibling_count = ancestors.last().map_or(1, |parent| parent.children_count);
115 debug_assert_op!(sibling_count != 0);
116 debug_assert_op!(index_as_child < sibling_count);
117 let sibling_count = unsafe { NonZeroUsize::new_unchecked(sibling_count) };
118 let node_info = NodeInfo {
119 name,
120 node_data,
121 row_index,
122 sibling_count,
123 index_as_child,
124 children_count,
125 };
126
127 initial_table.column_width.size_column_width =
128 max(initial_table.column_width.size_column_width, size.len());
129
130 initial_table.push_back(InitialRow {
131 node_info,
132 ancestors,
133 preceding_sibling,
134 size,
135 percentage,
136 });
137
138 ActResult { node_info }
139 },
140 Param {
141 index_as_child: 0,
142 ancestors: Vec::new(),
143 preceding_sibling: None,
144 },
145 );
146
147 initial_table
148}