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)]
use std::{
cell::RefCell,
fmt::{Debug, Display},
iter,
ops::Deref,
rc::{Rc, Weak},
slice::Iter,
};
// #[derive(Debug)]
// pub struct NodeRef(Rc<RefCell<Node>>);
#[derive(Debug)]
//these cant be just a type, as methods need to be impl'd on them.
pub struct FileRef(Rc<RefCell<File>>);
#[derive(Debug)]
pub struct DirRef(Rc<RefCell<Dir>>);
#[derive(Debug)]
pub struct WeakDirRef(Weak<RefCell<Dir>>);
#[derive(Debug)]
pub enum Node {
Dir(DirRef),
File(FileRef),
}
#[derive(Debug)]
pub struct File {
parent: WeakDirRef,
pub name: String,
pub size: usize,
}
#[derive(Debug, Default)]
#[derive(Default)]
pub struct Dir {
parent: Option<WeakDirRef>,
pub name: String,
@ -50,6 +45,7 @@ impl DirRef {
})
.sum()
}
fn new(name: String) -> Self {
DirRef(Rc::new(RefCell::new(Dir {
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.
fn add(&self, node: Node) {
fn add(&self, node: Node) -> Node {
let ret;
match node {
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);
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 {
fn get_parent(&self)-> &WeakDirRef {
fn get_parent(&self) -> &WeakDirRef {
&self.parent
}
}
@ -85,3 +103,104 @@ impl Dir {
&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!()
}
#[cfg(test)]
mod tests {
use super::*;
/* #[test]
fn test_parse() {
let input = "$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k";
assert_eq!(parse(input), 0);
} */
#[test]
fn test_parse_to_commands() {
let input = "$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k";
assert_eq!(
parse_to_commands(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: 484,
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")
}),
]),
]
)
}
}
// #[cfg(test)]
// mod tests {
// use super::*;
//
// /* #[test]
// fn test_parse() {
// let input = "$ cd /
// $ ls
// dir a
// 14848514 b.txt
// 8504156 c.dat
// dir d
// $ cd a
// $ ls
// dir e
// 29116 f
// 2557 g
// 62596 h.lst
// $ cd e
// $ ls
// 584 i
// $ cd ..
// $ cd ..
// $ cd d
// $ ls
// 4060174 j
// 8033020 d.log
// 5626152 d.ext
// 7214296 k";
// assert_eq!(parse(input), 0);
// } */
//
// #[test]
// fn test_parse_to_commands() {
// let input = "$ cd /
// $ ls
// dir a
// 14848514 b.txt
// 8504156 c.dat
// dir d
// $ cd a
// $ ls
// dir e
// 29116 f
// 2557 g
// 62596 h.lst
// $ cd e
// $ ls
// 584 i
// $ cd ..
// $ cd ..
// $ cd d
// $ ls
// 4060174 j
// 8033020 d.log
// 5626152 d.ext
// 7214296 k";
// assert_eq!(
// parse_to_commands(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: 484,
// 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")
// }),
// ]),
// ]
// )
// }
// }

View file

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

View file

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