hit a bit of a dead end. Can build a tree, but traversing it is HARD.

API sucks too.

Might start over.
This commit is contained in:
Gabe Venberg 2023-11-01 18:58:39 -05:00
parent 607a48eb3a
commit d578f1035e
4 changed files with 270 additions and 151 deletions

View file

@ -1,35 +1,30 @@
#![allow(unused)] #![allow(unused)]
use std::{ use std::{
cell::RefCell, cell::RefCell,
fmt::{Debug, Display},
iter,
ops::Deref, ops::Deref,
rc::{Rc, Weak}, rc::{Rc, Weak},
slice::Iter,
}; };
// #[derive(Debug)] //these cant be just a type, as methods need to be impl'd on them.
// pub struct NodeRef(Rc<RefCell<Node>>);
#[derive(Debug)]
pub struct FileRef(Rc<RefCell<File>>); pub struct FileRef(Rc<RefCell<File>>);
#[derive(Debug)]
pub struct DirRef(Rc<RefCell<Dir>>); pub struct DirRef(Rc<RefCell<Dir>>);
#[derive(Debug)]
pub struct WeakDirRef(Weak<RefCell<Dir>>); pub struct WeakDirRef(Weak<RefCell<Dir>>);
#[derive(Debug)]
pub enum Node { pub enum Node {
Dir(DirRef), Dir(DirRef),
File(FileRef), File(FileRef),
} }
#[derive(Debug)]
pub struct File { pub struct File {
parent: WeakDirRef, parent: WeakDirRef,
pub name: String, pub name: String,
pub size: usize, pub size: usize,
} }
#[derive(Debug, Default)] #[derive(Default)]
pub struct Dir { pub struct Dir {
parent: Option<WeakDirRef>, parent: Option<WeakDirRef>,
pub name: String, pub name: String,
@ -50,6 +45,7 @@ impl DirRef {
}) })
.sum() .sum()
} }
fn new(name: String) -> Self { fn new(name: String) -> Self {
DirRef(Rc::new(RefCell::new(Dir { DirRef(Rc::new(RefCell::new(Dir {
parent: None, parent: None,
@ -59,19 +55,41 @@ impl DirRef {
} }
//needs to be impled on the ref because of the need to get a weak backreference to self. //needs to be impled on the ref because of the need to get a weak backreference to self.
fn add(&self, node: Node) { fn add(&self, node: Node) -> Node {
let ret;
match node { match node {
Node::Dir(ref dir) => { Node::Dir(ref dir) => {
dir.0.borrow_mut().parent = Some(WeakDirRef(Rc::downgrade(&self.0))) dir.0.borrow_mut().parent = Some(WeakDirRef(Rc::downgrade(&self.0)));
ret = Node::Dir(DirRef(Rc::clone(&dir.0)));
}
Node::File(ref file) => {
file.0.borrow_mut().parent = WeakDirRef(Rc::downgrade(&self.0));
ret = Node::File(FileRef(Rc::clone(&file.0)));
} }
Node::File(ref file) => file.0.borrow_mut().parent = WeakDirRef(Rc::downgrade(&self.0)),
} }
self.0.borrow_mut().children.push(node); self.0.borrow_mut().children.push(node);
ret
}
//because a file always has a parent, it needs to be created off of a node.
fn new_file(&self, name: String, size: usize) -> FileRef {
let file = File {
parent: WeakDirRef(Rc::downgrade(&self.0)),
name,
size,
};
let file_ref = FileRef(Rc::new(RefCell::new(file)));
//have to unpack and repack to make a copy.
self.0
.borrow_mut()
.children
.push(Node::File(FileRef(Rc::clone(&file_ref.0))));
file_ref
} }
} }
impl File { impl File {
fn get_parent(&self)-> &WeakDirRef { fn get_parent(&self) -> &WeakDirRef {
&self.parent &self.parent
} }
} }
@ -85,3 +103,104 @@ impl Dir {
&self.parent &self.parent
} }
} }
impl Node {
fn get_dir(&self) -> Option<DirRef> {
match self {
Node::Dir(dir) => Some(DirRef(Rc::clone(&dir.0))),
Node::File(_) => None,
}
}
}
//transparent
impl Debug for DirRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// f.debug_tuple("DirRef").field(self.0.borrow().deref()).finish()
let this = self.0.borrow();
write!(f, "{:?}", this);
Ok(())
}
}
//transparent
impl Debug for FileRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// f.debug_tuple("FileRef").field(self.0.borrow().deref()).finish()
let this = self.0.borrow();
write!(f, "{:?}", this);
Ok(())
}
}
impl Debug for File {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// f.debug_struct("File")
// .field("name", &self.name)
// .field("size", &self.size)
// .finish()
write!(f, "- {} (file, size = {})", self.name, self.size);
Ok(())
}
}
impl Debug for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// match self {
// Self::Dir(arg0) => f.debug_tuple("Dir").field(arg0).finish(),
// Self::File(arg0) => f.debug_tuple("File").field(arg0).finish(),
// }
match self {
Node::Dir(dir) => write!(f, "{:?}", dir),
Node::File(file) => write!(f, "{:?}", file),
}
}
}
impl Debug for Dir {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// f.debug_struct("Dir")
// .field("name", &self.name)
// .field("children", &self.children)
// .finish()
writeln!(f, "- {} (dir)", self.name);
for node in &self.children {
//padding
for (index, line) in format!("{:#?}", node).lines().enumerate() {
writeln!(f, " {line}")?;
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dir_tree_sizes() {
let root = DirRef::new("/".to_string());
let a = root.add(Node::Dir(DirRef::new("a".to_string())));
let e = a
.get_dir()
.unwrap()
.add(Node::Dir(DirRef::new("e".to_string())));
let i = e.get_dir().unwrap().new_file("i".to_string(), 584);
let f = a.get_dir().unwrap().new_file("f".to_string(), 29116);
let g = a.get_dir().unwrap().new_file("g".to_string(), 2557);
let h = a.get_dir().unwrap().new_file("h.lst".to_string(), 62596);
let b = root.new_file("b.txt".to_string(), 14848514);
let c = root.new_file("c.txt".to_string(), 8504156);
let d = root.add(Node::Dir(DirRef::new("a".to_string())));
let j = d.get_dir().unwrap().new_file("j".to_string(), 4060174);
let dlog = d.get_dir().unwrap().new_file("d.log".to_string(), 8033020);
let dext = d.get_dir().unwrap().new_file("d.ext".to_string(), 5626152);
let k = d.get_dir().unwrap().new_file("k".to_string(), 7214296);
println!("{:#?}", root);
assert_eq!(e.get_dir().unwrap().total_size(), 584);
assert_eq!(a.get_dir().unwrap().total_size(), 94853);
assert_eq!(d.get_dir().unwrap().total_size(), 24933642);
assert_eq!(root.total_size(), 48381165)
}
}

View file

@ -35,122 +35,122 @@ pub fn parse_to_commands(input: &str) -> Vec<Command> {
unimplemented!() unimplemented!()
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use super::*; // use super::*;
//
/* #[test] // /* #[test]
fn test_parse() { // fn test_parse() {
let input = "$ cd / // let input = "$ cd /
$ ls // $ ls
dir a // dir a
14848514 b.txt // 14848514 b.txt
8504156 c.dat // 8504156 c.dat
dir d // dir d
$ cd a // $ cd a
$ ls // $ ls
dir e // dir e
29116 f // 29116 f
2557 g // 2557 g
62596 h.lst // 62596 h.lst
$ cd e // $ cd e
$ ls // $ ls
584 i // 584 i
$ cd .. // $ cd ..
$ cd .. // $ cd ..
$ cd d // $ cd d
$ ls // $ ls
4060174 j // 4060174 j
8033020 d.log // 8033020 d.log
5626152 d.ext // 5626152 d.ext
7214296 k"; // 7214296 k";
assert_eq!(parse(input), 0); // assert_eq!(parse(input), 0);
} */ // } */
//
#[test] // #[test]
fn test_parse_to_commands() { // fn test_parse_to_commands() {
let input = "$ cd / // let input = "$ cd /
$ ls // $ ls
dir a // dir a
14848514 b.txt // 14848514 b.txt
8504156 c.dat // 8504156 c.dat
dir d // dir d
$ cd a // $ cd a
$ ls // $ ls
dir e // dir e
29116 f // 29116 f
2557 g // 2557 g
62596 h.lst // 62596 h.lst
$ cd e // $ cd e
$ ls // $ ls
584 i // 584 i
$ cd .. // $ cd ..
$ cd .. // $ cd ..
$ cd d // $ cd d
$ ls // $ ls
4060174 j // 4060174 j
8033020 d.log // 8033020 d.log
5626152 d.ext // 5626152 d.ext
7214296 k"; // 7214296 k";
assert_eq!( // assert_eq!(
parse_to_commands(input), // parse_to_commands(input),
vec![ // vec![
Command::CdRoot, // Command::CdRoot,
Command::Ls(vec![ // Command::Ls(vec![
LsEntry::Dir(String::from("a")), // LsEntry::Dir(String::from("a")),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 14848514, // size: 14848514,
name: String::from("b.txt") // name: String::from("b.txt")
}), // }),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 8504156, // size: 8504156,
name: String::from("c.dat") // name: String::from("c.dat")
}), // }),
LsEntry::Dir(String::from("d")) // LsEntry::Dir(String::from("d"))
]), // ]),
Command::Cd(String::from("a")), // Command::Cd(String::from("a")),
Command::Ls(vec![ // Command::Ls(vec![
LsEntry::Dir(String::from("e")), // LsEntry::Dir(String::from("e")),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 29116, // size: 29116,
name: String::from("f") // name: String::from("f")
}), // }),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 2557, // size: 2557,
name: String::from("g") // name: String::from("g")
}), // }),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 62596, // size: 62596,
name: String::from("h.lst") // name: String::from("h.lst")
}), // }),
]), // ]),
Command::Cd(String::from("e")), // Command::Cd(String::from("e")),
Command::Ls(vec![LsEntry::File(ParseFile { // Command::Ls(vec![LsEntry::File(ParseFile {
size: 484, // size: 484,
name: String::from("i") // name: String::from("i")
}),]), // }),]),
Command::CdUp, // Command::CdUp,
Command::CdUp, // Command::CdUp,
Command::Cd(String::from("d")), // Command::Cd(String::from("d")),
Command::Ls(vec![ // Command::Ls(vec![
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 4060174, // size: 4060174,
name: String::from("j") // name: String::from("j")
}), // }),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 8033020, // size: 8033020,
name: String::from("d.log") // name: String::from("d.log")
}), // }),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 5626152, // size: 5626152,
name: String::from("d.ext") // name: String::from("d.ext")
}), // }),
LsEntry::File(ParseFile { // LsEntry::File(ParseFile {
size: 7214296, // size: 7214296,
name: String::from("k") // name: String::from("k")
}), // }),
]), // ]),
] // ]
) // )
} // }
} // }

View file

@ -6,12 +6,12 @@ pub fn part1() -> usize {
unimplemented!() unimplemented!()
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use super::*; // use super::*;
//
#[test] // #[test]
fn test_part1() { // fn test_part1() {
assert_eq!(part1(), 0); // assert_eq!(part1(), 0);
} // }
} // }

View file

@ -6,12 +6,12 @@ pub fn part2() -> usize {
unimplemented!() unimplemented!()
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use super::*; // use super::*;
//
#[test] // #[test]
fn test_part2() { // fn test_part2() {
assert_eq!(part2(), 0); // assert_eq!(part2(), 0);
} // }
} // }