ITS WORKING!!
This commit is contained in:
parent
824321c660
commit
35a5c043a0
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue