Use more rusty patterns and preallocate enough space

This commit is contained in:
Xavier L'Heureux
2019-11-24 21:57:16 -05:00
parent 86b3cccaf6
commit f8ce6c97bf
2 changed files with 29 additions and 34 deletions
+11 -12
View File
@@ -109,18 +109,14 @@ fn main() {
} }
fn build_tree(biggest_ones: Vec<(String, u64)>, depth: Option<u64>) -> Node { fn build_tree(biggest_ones: Vec<(String, u64)>, depth: Option<u64>) -> Node {
let mut top_parent = Node { let mut top_parent = Node::default();
name: "".to_string(),
size: 0,
children: vec![],
};
// assume sorted order // assume sorted order
for b in biggest_ones { for b in biggest_ones {
let n = Node { let n = Node {
name: b.0, name: b.0,
size: b.1, size: b.1,
children: vec![], children: Vec::default(),
}; };
recursively_build_tree(&mut top_parent, n, depth) recursively_build_tree(&mut top_parent, n, depth)
} }
@@ -133,13 +129,16 @@ fn recursively_build_tree(parent_node: &mut Node, new_node: Node, depth: Option<
Some(0) => return, Some(0) => return,
Some(d) => Some(d - 1), Some(d) => Some(d - 1),
}; };
for c in parent_node.children.iter_mut() { if let Some(c) = parent_node
if new_node.name.starts_with(&c.name) { .children
return recursively_build_tree(&mut *c, new_node, new_depth); .iter_mut()
} .find(|c| new_node.name.starts_with(&c.name))
{
recursively_build_tree(&mut *c, new_node, new_depth);
} else {
let temp = Box::<Node>::new(new_node);
parent_node.children.push(temp);
} }
let temp = Box::<Node>::new(new_node);
parent_node.children.push(temp);
} }
#[cfg(test)] #[cfg(test)]
+18 -22
View File
@@ -1,13 +1,14 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::path::PathBuf;
use jwalk::WalkDir; use jwalk::WalkDir;
mod platform; mod platform;
use self::platform::*; use self::platform::*;
#[derive(Debug)] #[derive(Debug, Default)]
pub struct Node { pub struct Node {
pub name: String, pub name: String,
pub size: u64, pub size: u64,
@@ -15,26 +16,25 @@ pub struct Node {
} }
pub fn simplify_dir_names(filenames: Vec<&str>) -> HashSet<String> { pub fn simplify_dir_names(filenames: Vec<&str>) -> HashSet<String> {
let mut top_level_names: HashSet<String> = HashSet::new(); let mut top_level_names: HashSet<String> = HashSet::with_capacity(filenames.len());
let mut to_remove: Vec<String> = Vec::with_capacity(filenames.len());
for t in filenames { for t in filenames {
let top_level_name = ensure_end_slash(t); let top_level_name = ensure_end_slash(t);
let mut can_add = true; let mut can_add = true;
let mut to_remove: Vec<String> = Vec::new();
for tt in top_level_names.iter() { for tt in top_level_names.iter() {
let temp = tt.to_string(); if top_level_name.starts_with(tt) {
if top_level_name.starts_with(&temp) {
can_add = false; can_add = false;
} else if tt.starts_with(&top_level_name) { } else if tt.starts_with(&top_level_name) {
to_remove.push(temp); to_remove.push(tt.to_string());
} }
} }
for tr in to_remove { to_remove.sort_unstable();
top_level_names.remove(&tr); top_level_names.retain(|tr| to_remove.binary_search(tr).is_err());
} to_remove.clear();
if can_add { if can_add {
top_level_names.insert(strip_end_slash(t)); top_level_names.insert(strip_end_slash(t).to_owned());
} }
} }
@@ -63,10 +63,9 @@ pub fn ensure_end_slash(s: &str) -> String {
new_name + "/" new_name + "/"
} }
pub fn strip_end_slash(s: &str) -> String { pub fn strip_end_slash(mut new_name: &str) -> &str {
let mut new_name = String::from(s);
while (new_name.ends_with('/') || new_name.ends_with("/.")) && new_name.len() > 1 { while (new_name.ends_with('/') || new_name.ends_with("/.")) && new_name.len() > 1 {
new_name.pop(); new_name = &new_name[..new_name.len() - 1];
} }
new_name new_name
} }
@@ -93,16 +92,13 @@ fn examine_dir(
} }
} }
// This path and all its parent paths have their counter incremented // This path and all its parent paths have their counter incremented
let mut e_path = e.path(); for path_name in PathBuf::from(e.path()).ancestors() {
loop { let path_name = path_name.to_string_lossy();
let path_name = e_path.to_string_lossy().to_string(); let s = data.entry(path_name.to_string()).or_insert(0);
let s = data.entry(path_name.clone()).or_insert(0);
*s += size; *s += size;
if path_name == top_dir || path_name == "/" { if path_name == top_dir {
break; break;
} }
assert!(path_name != "");
e_path.pop();
} }
} }
None => *file_count_no_permission += 1, None => *file_count_no_permission += 1,
@@ -124,7 +120,7 @@ pub fn sort_by_size_first_name_second(a: &(String, u64), b: &(String, u64)) -> O
pub fn sort(data: HashMap<String, u64>) -> Vec<(String, u64)> { pub fn sort(data: HashMap<String, u64>) -> Vec<(String, u64)> {
let mut new_l: Vec<(String, u64)> = data.iter().map(|(a, b)| (a.clone(), *b)).collect(); let mut new_l: Vec<(String, u64)> = data.iter().map(|(a, b)| (a.clone(), *b)).collect();
new_l.sort_by(|a, b| sort_by_size_first_name_second(&a, &b)); new_l.sort_unstable_by(sort_by_size_first_name_second);
new_l new_l
} }
@@ -141,7 +137,7 @@ pub fn trim_deep_ones(
max_depth: u64, max_depth: u64,
top_level_names: &HashSet<String>, top_level_names: &HashSet<String>,
) -> Vec<(String, u64)> { ) -> Vec<(String, u64)> {
let mut result: Vec<(String, u64)> = vec![]; let mut result: Vec<(String, u64)> = Vec::with_capacity(input.len() * top_level_names.len());
for name in top_level_names { for name in top_level_names {
let my_max_depth = name.matches('/').count() + max_depth as usize; let my_max_depth = name.matches('/').count() + max_depth as usize;