parsing to a tree, ugly tree traversal.

This commit is contained in:
Gabe Venberg 2023-11-17 23:52:42 -06:00
parent 35a5c043a0
commit 1df04702a2
2 changed files with 191 additions and 38 deletions

View file

@ -22,7 +22,7 @@ pub enum FileTreeError {
type WeakNodeRef = Weak<RefCell<Node>>;
#[derive(Debug)]
pub struct NodeRef(Rc<RefCell<Node>>);
pub struct NodeRef(pub Rc<RefCell<Node>>);
impl Deref for NodeRef {
type Target = Rc<RefCell<Node>>;
@ -44,7 +44,7 @@ impl From<NodeRef> for Rc<RefCell<Node>> {
}
}
impl Display for NodeRef{
impl Display for NodeRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.borrow())
}
@ -55,6 +55,28 @@ impl NodeRef {
node.set_parent(self);
self.borrow_mut().add_children(node)
}
pub fn new_dir(name: String) -> NodeRef {
NodeRef(Rc::new(RefCell::new(Node::new_dir(name))))
}
pub fn add_file(&mut self, name: String, size: usize) -> Result<NodeRef, FileTreeError> {
self.add_node(Node::new_file(name, size))
}
pub fn add_dir(&mut self, name: String) -> Result<NodeRef, FileTreeError> {
self.add_node(Node::new_dir(name))
}
pub fn get_all_dirs(&self) -> Vec<NodeRef> {
let mut ret = Vec::new();
match &self.borrow().contents {
Contents::Size(_) => {}
Contents::Children(c) => {
ret.push(NodeRef(Rc::clone(self)));
for node in c {
ret.append(&mut node.get_all_dirs())
}
}
};
ret
}
}
#[derive(Debug)]
@ -161,7 +183,7 @@ impl Node {
}
}
impl Display for Node{
impl Display for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "- {} {}", self.name, self.contents)
}
@ -197,43 +219,87 @@ mod tests {
#[test]
fn test_dir_construction() {
let mut root = NodeRef(Rc::new(RefCell::new(Node::new_dir("/".to_string()))));
let mut root = NodeRef::new_dir("/".to_string());
let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap();
cursor = cursor.add_node(Node::new_dir("e".to_string())).unwrap();
cursor
.add_node(Node::new_file("i".to_string(), 584))
.unwrap();
cursor = cursor.add_dir("e".to_string()).unwrap();
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor
.add_node(Node::new_file("f".to_string(), 29116))
.unwrap();
cursor
.add_node(Node::new_file("g".to_string(), 2557))
.unwrap();
cursor
.add_node(Node::new_file("h.lst".to_string(), 62596))
.unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor
.add_node(Node::new_file("b.txt".to_string(), 14848514))
.unwrap();
cursor
.add_node(Node::new_file("c.dat".to_string(), 8504156))
.unwrap();
cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap();
cursor
.add_node(Node::new_file("j".to_string(), 4060174))
.unwrap();
cursor
.add_node(Node::new_file("d.log".to_string(), 8033020))
.unwrap();
cursor
.add_node(Node::new_file("d.ext".to_string(), 5626152))
.unwrap();
cursor
.add_node(Node::new_file("k".to_string(), 7214296))
.unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_dir("d".to_string()).unwrap();
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
println!("{}", root);
}
#[test]
fn test_size_calcs() {
let mut root = NodeRef::new_dir("/".to_string());
let mut dirs: Vec<NodeRef> = Vec::new();
let mut cursor = root.add_dir("a".to_string()).unwrap();
dirs.push(NodeRef(Rc::clone(&cursor)));
cursor = cursor.add_dir("e".to_string()).unwrap();
dirs.push(NodeRef(Rc::clone(&cursor)));
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap();
dirs.push(NodeRef(Rc::clone(&cursor)));
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
assert_eq!(Rc::clone(dirs[0].deref()).borrow().get_total_size(), 94853);
assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 584);
assert_eq!(
Rc::clone(dirs[2].deref()).borrow().get_total_size(),
24933642
);
}
#[test]
fn test_get_all_dirs() {
let mut root = NodeRef::new_dir("/".to_string());
let mut cursor = root.add_dir("a".to_string()).unwrap();
cursor = cursor.add_dir("e".to_string()).unwrap();
cursor.add_file("i".to_string(), 584).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("f".to_string(), 29116).unwrap();
cursor.add_file("g".to_string(), 2557).unwrap();
cursor.add_file("h.lst".to_string(), 62596).unwrap();
cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
cursor.add_file("b.txt".to_string(), 14848514).unwrap();
cursor.add_file("c.dat".to_string(), 8504156).unwrap();
cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap();
cursor.add_file("j".to_string(), 4060174).unwrap();
cursor.add_file("d.log".to_string(), 8033020).unwrap();
cursor.add_file("d.ext".to_string(), 5626152).unwrap();
cursor.add_file("k".to_string(), 7214296).unwrap();
let dirs = root.get_all_dirs();
let sizes: Vec<usize> = dirs.iter().map(|d| d.borrow().get_total_size()).collect();
println!("{:?}", sizes);
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
assert_eq!(
Rc::clone(dirs[0].deref()).borrow().get_total_size(),
48381165
);
assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 94853);
assert_eq!(Rc::clone(dirs[2].deref()).borrow().get_total_size(), 584);
assert_eq!(
Rc::clone(dirs[3].deref()).borrow().get_total_size(),
24933642
);
}
}

View file

@ -1,4 +1,7 @@
#![allow(unused)]
use std::ops::Deref;
use std::{cell::RefCell, rc::Rc};
use crate::file_tree::*;
use once_cell::sync::Lazy;
use regex::Regex;
@ -77,8 +80,29 @@ pub fn parse(input: &str) -> Node {
unimplemented!()
}
pub fn commands_to_tree(input: Vec<Command>) -> Node {
unimplemented!()
pub fn commands_to_tree(input: Vec<Command>) -> NodeRef {
let root = NodeRef::new_dir("/".to_string());
let mut cursor = NodeRef(Rc::clone(&root));
for command in input {
match command {
Command::CdRoot => cursor = NodeRef(Rc::clone(&root)),
Command::CdUp => cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(),
Command::Cd(name) => cursor = cursor.add_dir(name).unwrap(),
Command::Ls(ls) => {
for entry in ls {
match entry {
LsEntry::Dir(d) => {
//dirs dont exist until you cd into them.
}
LsEntry::File(f) => {
cursor.add_file(f.name, f.size);
}
};
}
}
}
}
root
}
#[cfg(test)]
@ -173,4 +197,67 @@ mod tests {
]
)
}
#[test]
fn test_commands_to_tree() {
let input = vec![
Command::CdRoot,
Command::Ls(vec![
LsEntry::Dir(String::from("a")),
LsEntry::File(ParseFile {
size: 14848514,
name: String::from("b.txt"),
}),
LsEntry::File(ParseFile {
size: 8504156,
name: String::from("c.dat"),
}),
LsEntry::Dir(String::from("d")),
]),
Command::Cd(String::from("a")),
Command::Ls(vec![
LsEntry::Dir(String::from("e")),
LsEntry::File(ParseFile {
size: 29116,
name: String::from("f"),
}),
LsEntry::File(ParseFile {
size: 2557,
name: String::from("g"),
}),
LsEntry::File(ParseFile {
size: 62596,
name: String::from("h.lst"),
}),
]),
Command::Cd(String::from("e")),
Command::Ls(vec![LsEntry::File(ParseFile {
size: 584,
name: String::from("i"),
})]),
Command::CdUp,
Command::CdUp,
Command::Cd(String::from("d")),
Command::Ls(vec![
LsEntry::File(ParseFile {
size: 4060174,
name: String::from("j"),
}),
LsEntry::File(ParseFile {
size: 8033020,
name: String::from("d.log"),
}),
LsEntry::File(ParseFile {
size: 5626152,
name: String::from("d.ext"),
}),
LsEntry::File(ParseFile {
size: 7214296,
name: String::from("k"),
}),
]),
];
let tree = commands_to_tree(input);
println!("{}", tree);
assert_eq!(Rc::clone(tree.deref()).borrow().get_total_size(), 48381165)
}
}