parsing to a tree, ugly tree traversal.
This commit is contained in:
		
							parent
							
								
									35a5c043a0
								
							
						
					
					
						commit
						1df04702a2
					
				
					 2 changed files with 191 additions and 38 deletions
				
			
		| 
						 | 
					@ -22,7 +22,7 @@ pub enum FileTreeError {
 | 
				
			||||||
type WeakNodeRef = Weak<RefCell<Node>>;
 | 
					type WeakNodeRef = Weak<RefCell<Node>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct NodeRef(Rc<RefCell<Node>>);
 | 
					pub struct NodeRef(pub Rc<RefCell<Node>>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Deref for NodeRef {
 | 
					impl Deref for NodeRef {
 | 
				
			||||||
    type Target = Rc<RefCell<Node>>;
 | 
					    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 {
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        write!(f, "{}", self.borrow())
 | 
					        write!(f, "{}", self.borrow())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,28 @@ impl NodeRef {
 | 
				
			||||||
        node.set_parent(self);
 | 
					        node.set_parent(self);
 | 
				
			||||||
        self.borrow_mut().add_children(node)
 | 
					        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)]
 | 
					#[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 {
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        write!(f, "- {} {}", self.name, self.contents)
 | 
					        write!(f, "- {} {}", self.name, self.contents)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -197,43 +219,87 @@ mod tests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn test_dir_construction() {
 | 
					    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();
 | 
					        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 = cursor.add_dir("e".to_string()).unwrap();
 | 
				
			||||||
        cursor
 | 
					        cursor.add_file("i".to_string(), 584).unwrap();
 | 
				
			||||||
            .add_node(Node::new_file("i".to_string(), 584))
 | 
					 | 
				
			||||||
            .unwrap();
 | 
					 | 
				
			||||||
        cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
 | 
					        cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
 | 
				
			||||||
        cursor
 | 
					        cursor.add_file("f".to_string(), 29116).unwrap();
 | 
				
			||||||
            .add_node(Node::new_file("f".to_string(), 29116))
 | 
					        cursor.add_file("g".to_string(), 2557).unwrap();
 | 
				
			||||||
            .unwrap();
 | 
					        cursor.add_file("h.lst".to_string(), 62596).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 = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
 | 
					        cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap();
 | 
				
			||||||
        cursor
 | 
					        cursor.add_file("b.txt".to_string(), 14848514).unwrap();
 | 
				
			||||||
            .add_node(Node::new_file("b.txt".to_string(), 14848514))
 | 
					        cursor.add_file("c.dat".to_string(), 8504156).unwrap();
 | 
				
			||||||
            .unwrap();
 | 
					        cursor = cursor.add_dir("d".to_string()).unwrap();
 | 
				
			||||||
        cursor
 | 
					        cursor.add_file("j".to_string(), 4060174).unwrap();
 | 
				
			||||||
            .add_node(Node::new_file("c.dat".to_string(), 8504156))
 | 
					        cursor.add_file("d.log".to_string(), 8033020).unwrap();
 | 
				
			||||||
            .unwrap();
 | 
					        cursor.add_file("d.ext".to_string(), 5626152).unwrap();
 | 
				
			||||||
        cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap();
 | 
					        cursor.add_file("k".to_string(), 7214296).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();
 | 
					 | 
				
			||||||
        assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
 | 
					        assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
 | 
				
			||||||
        println!("{}", root);
 | 
					        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
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,7 @@
 | 
				
			||||||
#![allow(unused)]
 | 
					#![allow(unused)]
 | 
				
			||||||
 | 
					use std::ops::Deref;
 | 
				
			||||||
 | 
					use std::{cell::RefCell, rc::Rc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::file_tree::*;
 | 
					use crate::file_tree::*;
 | 
				
			||||||
use once_cell::sync::Lazy;
 | 
					use once_cell::sync::Lazy;
 | 
				
			||||||
use regex::Regex;
 | 
					use regex::Regex;
 | 
				
			||||||
| 
						 | 
					@ -77,8 +80,29 @@ pub fn parse(input: &str) -> Node {
 | 
				
			||||||
    unimplemented!()
 | 
					    unimplemented!()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn commands_to_tree(input: Vec<Command>) -> Node {
 | 
					pub fn commands_to_tree(input: Vec<Command>) -> NodeRef {
 | 
				
			||||||
    unimplemented!()
 | 
					    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)]
 | 
					#[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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue