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>>;
 | 
			
		||||
 | 
			
		||||
#[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
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue