ITS WORKING!!

This commit is contained in:
Gabe Venberg 2023-11-16 18:17:25 -06:00
parent 824321c660
commit 35a5c043a0

View file

@ -1,5 +1,6 @@
use std::{
cell::RefCell,
fmt::Display,
ops::Deref,
rc::{Rc, Weak},
};
@ -12,6 +13,10 @@ pub enum FileTreeError {
IsFile,
#[error("File operation on directory")]
IsDir,
#[error("File not found")]
FileNotFound,
#[error("File already exists")]
FileAlreadyExists,
}
type WeakNodeRef = Weak<RefCell<Node>>;
@ -39,6 +44,19 @@ impl From<NodeRef> for Rc<RefCell<Node>> {
}
}
impl Display for NodeRef{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.borrow())
}
}
impl NodeRef {
pub fn add_node(&mut self, mut node: Node) -> Result<NodeRef, FileTreeError> {
node.set_parent(self);
self.borrow_mut().add_children(node)
}
}
#[derive(Debug)]
pub struct Node {
pub name: String,
@ -47,9 +65,60 @@ pub struct Node {
}
impl Node {
pub fn new_dir(name: String) -> Node {
Node {
name,
parent: None,
contents: Contents::Children(Vec::new()),
}
}
pub fn new_file(name: String, size: usize) -> Node {
Node {
name,
parent: None,
contents: Contents::Size(size),
}
}
pub fn get_total_size(&self) -> usize {
match &self.contents {
Contents::Size(s) => *s,
Contents::Children(c) => c.iter().map(|f| f.borrow().get_total_size()).sum(),
}
}
fn set_parent(&mut self, newparent: &NodeRef) {
self.parent = Some(Rc::downgrade(newparent));
}
// does not set the parent, needs to be done on the NodeRef. (this is why this func isnt pub).
// takes onwership of the node to make sure its not owned by another tree.
fn add_children(&mut self, node: Node) -> Result<NodeRef, FileTreeError> {
match self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(ref mut c) => {
for file in c.iter() {
if file.borrow().name == node.name {
return Err(FileTreeError::FileAlreadyExists);
}
}
let rc = Rc::new(RefCell::new(node));
c.push(NodeRef(Rc::clone(&rc)));
Ok(NodeRef(Rc::clone(&rc)))
}
}
}
pub fn remove_child_by_name(&mut self, name: &str) -> Result<(), FileTreeError> {
match self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(ref mut c) => {
for (i, file) in c.iter().enumerate() {
if file.borrow().name == name {
c.remove(i);
return Ok(());
}
}
Err(FileTreeError::FileNotFound)
}
}
}
pub fn get_parent(&self) -> Option<NodeRef> {
match &self.parent {
Some(w) => Some(NodeRef(w.clone().upgrade()?)),
@ -77,6 +146,25 @@ impl Node {
Contents::Children(c) => Ok(c.iter().map(|n| NodeRef(Rc::clone(n)))),
}
}
pub fn get_child_by_name(&self, name: &str) -> Result<NodeRef, FileTreeError> {
match &self.contents {
Contents::Size(_) => Err(FileTreeError::IsFile),
Contents::Children(c) => {
for file in c.iter() {
if file.borrow().name == name {
return Ok(NodeRef(Rc::clone(file)));
}
}
Err(FileTreeError::FileNotFound)
}
}
}
}
impl Display for Node{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "- {} {}", self.name, self.contents)
}
}
#[derive(Debug)]
@ -84,3 +172,68 @@ pub enum Contents {
Size(usize),
Children(Vec<NodeRef>),
}
impl Display for Contents {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Contents::Size(s) => write!(f, "(file, size = {})", s),
Contents::Children(c) => {
writeln!(f, "(dir)").expect("I have no clue how this could fail");
for node in c {
//padding
for line in format!("{}", node).lines() {
writeln!(f, " {line}")?;
}
}
Ok(())
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dir_construction() {
let mut root = NodeRef(Rc::new(RefCell::new(Node::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 = 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 = 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();
assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165);
println!("{}", root);
}
}