//! This data structure is a generic tree which can contain any data. That data itself need to keep //! track of its own tree structure. //! //! This surely already exists. I am created it to test my own ability to do things in Rust. use std::{ cell::{Ref, RefCell}, collections::VecDeque, rc::Rc, }; #[derive(Debug)] pub enum Tree { Empty, Root(Node), } impl Default for Tree { fn default() -> Self { Tree::Empty } } impl Tree { pub fn set_value(&mut self, value: T) { *self = Tree::Root(Node::new(value)); } /// Use a breadth-first-search pattern to find a node, returning the node if found. pub fn find_bfs<'a, F>(&'a self, op: F) -> Option> where F: FnOnce(&T) -> bool + Copy, { let mut queue: VecDeque> = match self { Tree::Empty => VecDeque::new(), Tree::Root(node) => { let mut queue = VecDeque::new(); queue.push_back(node.clone()); queue } }; while let Some(node) = queue.pop_front() { if op(&node.value()) { return Some(node.clone()); } for child in node.children().iter() { queue.push_back(child.clone()) } } None } } // By using the Rc container here, I'm able to make Node easily clonable while still // having the contents be shared. This means that I can change the tree structure without having to // make the visible objects mutable. // // This feels like cheating the type system. // // However, since I've moved the RefCell inside of the node, I can borrow the node multiple times // in a traversal function and I can make changes to nodes that I find. #[derive(Debug)] pub struct Node(Rc>>); impl Clone for Node { fn clone(&self) -> Self { Node(Rc::clone(&self.0)) } } #[derive(Debug)] struct Node_ { value: T, children: Vec>, } impl Node { pub fn new(value: T) -> Self { Self(Rc::new(RefCell::new(Node_ { value, children: vec![], }))) } // I am copying the value because I don't have a mechanism for keeping the borrow ref active. // My next step is to figure out how to keep the borrow ref active so that I don't have to // clone the item. Then I could drop the Clone constraint. pub fn value<'a>(&'a self) -> Ref { Ref::map(self.0.borrow(), |v| &v.value) } pub fn children<'a>(&'a self) -> Ref>> { Ref::map(self.0.borrow(), |v| &v.children) } pub fn add_child_node(&self, child: Node) { self.0.borrow_mut().children.push(child) } pub fn add_child_value(&self, value: T) { self.0.borrow_mut().children.push(Node::new(value)) } } #[cfg(test)] mod tests { use super::*; #[test] fn can_find_node_in_tree() { let mut tree = Tree::default(); tree.set_value(15); assert!(tree.find_bfs(|val| *val == 15).is_some()); assert!(tree.find_bfs(|val| *val == 16).is_none()); let node = tree.find_bfs(|val| *val == 15).unwrap(); node.add_child_value(20); assert!(tree.find_bfs(|val| *val == 20).is_some()); } #[test] fn node_can_add_children() { let n = Node::new(15); n.add_child_value(20); assert_eq!(*n.value(), 15); // assert_eq!(n.children(), vec![Rc::new(RefCell::new(Node::new(20)))]); } }