diff --git a/Cargo.toml b/Cargo.toml index 543b289..c00e978 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "id_tree" -version = "1.0.2" +version = "1.1.0" authors = ["Ian Burns "] description = "A library for creating and modifying Tree structures." documentation = "https://docs.rs/id_tree" diff --git a/examples/basic.rs b/examples/basic.rs index 4fa74f3..9c1a338 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -21,30 +21,17 @@ fn main() { tree.insert(Node::new(4), UnderNode(&child_id)).unwrap(); println!("Post-order:"); - print_post_order(&tree, &root_id); - println!(); - - println!("Pre-order:"); - print_pre_order(&tree, &root_id); - println!(); -} - -fn print_pre_order(tree: &Tree, node_id: &NodeId) { - let node_ref = tree.get(node_id).unwrap(); - print!("{}, ", node_ref.data()); - - for child_id in node_ref.children() { - print_pre_order(tree, &child_id); + for node in tree.traverse_post_order(&root_id).unwrap() { + print!("{}, ", node.data()); } -} -fn print_post_order(tree: &Tree, node_id: &NodeId) { - let node_ref = tree.get(node_id).unwrap(); + println!(); + println!("Pre-order:"); - for child_id in node_ref.children() { - print_post_order(tree, &child_id); + for node in tree.traverse_pre_order(&root_id).unwrap() { + print!("{}, ", node.data()); } - print!("{}, ", node_ref.data()); + println!(); } diff --git a/src/behaviors.rs b/src/behaviors.rs index 12f0090..d166205 100644 --- a/src/behaviors.rs +++ b/src/behaviors.rs @@ -1,4 +1,4 @@ -use super::NodeId; +use NodeId; /// /// Describes the possible behaviors of the `Tree::remove_node` method. diff --git a/src/lib.rs b/src/lib.rs index 2ac9eef..e032d3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,19 +36,11 @@ //! tree.insert(Node::new(3), UnderNode(&child_id)).unwrap(); //! tree.insert(Node::new(4), UnderNode(&child_id)).unwrap(); //! -//! println!("Pre-order:"); -//! print_pre_order(&tree, &root_id); -//! // results in the output "0, 1, 3, 4, 2, " -//! } -//! -//! fn print_pre_order(tree: &Tree, node_id: &NodeId) { -//! let node_ref = tree.get(node_id).unwrap(); -//! -//! print!("{}, ", node_ref.data()); -//! -//! for child_id in node_ref.children() { -//! print_pre_order(tree, &child_id); +//! println!("Post-order:"); +//! for node in tree.traverse_pre_order(&root_id).unwrap() { +//! print!("{}, ", node.data()); //! } +//! // results in the output "0, 1, 3, 4, 2, " //! } //! ``` //! @@ -90,6 +82,13 @@ pub use node::NodeBuilder; pub use node::Node; pub use tree::TreeBuilder; pub use tree::Tree; +pub use tree::iterators::Ancestors; +pub use tree::iterators::AncestorIds; +pub use tree::iterators::Children; +pub use tree::iterators::ChildrenIds; +pub use tree::iterators::PreOrderTraversal; +pub use tree::iterators::PostOrderTraversal; +pub use tree::iterators::LevelOrderTraversal; /// /// An identifier used to differentiate between `Node`s within a `Tree`. diff --git a/src/node.rs b/src/node.rs index 9098405..3fbd832 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,5 +1,5 @@ -use super::NodeId; -use super::MutableNode; +use NodeId; +use MutableNode; /// /// A `Node` builder that provides more control over how a `Node` is created. diff --git a/src/tree/iterators.rs b/src/tree/iterators.rs new file mode 100644 index 0000000..befbf0d --- /dev/null +++ b/src/tree/iterators.rs @@ -0,0 +1,500 @@ +use std::slice::Iter; +use std::vec::IntoIter; +use std::collections::VecDeque; + +use Tree; +use Node; +use NodeId; +use tree::IteratorNew; + +/// +/// An Iterator over the ancestors of a `Node`. +/// +/// Iterates over the ancestor `Node`s of a given `Node` in the `Tree`. Each call to `next` will +/// return an immutable reference to the next `Node` up the `Tree`. +/// +pub struct Ancestors<'a, T: 'a> { + tree: &'a Tree, + node_id: Option, +} + +impl<'a, T> IteratorNew<'a, T, Ancestors<'a, T>> for Ancestors<'a, T> { + fn new(tree: &'a Tree, node_id: NodeId) -> Ancestors<'a, T> { + Ancestors { + tree: tree, + node_id: Some(node_id), + } + } +} + +impl<'a, T> Iterator for Ancestors<'a, T> { + type Item = &'a Node; + + fn next(&mut self) -> Option<&'a Node> { + if let Some(current_id) = self.node_id.clone() { + if let Some(parent_id) = self.tree.get_unsafe(¤t_id).parent() { + let parent = self.tree.get_unsafe(&parent_id); + self.node_id = Some(parent_id.clone()); + return Some(parent); + } else { + self.node_id = None; + } + } + None + } +} + +/// +/// An Iterator over the ancestors of a `Node`. +/// +/// Iterates over `NodeId`s instead of over the `Node`s themselves. +/// +pub struct AncestorIds<'a, T: 'a> { + tree: &'a Tree, + node_id: Option, +} + +impl<'a, T> IteratorNew<'a, T, AncestorIds<'a, T>> for AncestorIds<'a, T> { + fn new(tree: &'a Tree, node_id: NodeId) -> AncestorIds<'a, T> { + AncestorIds { + tree: tree, + node_id: Some(node_id), + } + } +} + +impl<'a, T> Iterator for AncestorIds<'a, T> { + type Item = &'a NodeId; + + fn next(&mut self) -> Option<&'a NodeId> { + if let Some(current_id) = self.node_id.clone() { + if let Some(parent_id) = self.tree.get_unsafe(¤t_id).parent() { + self.node_id = Some(parent_id.clone()); + return Some(parent_id); + } else { + self.node_id = None; + } + } + None + } +} + +/// +/// An Iterator over the children of a `Node`. +/// +/// Iterates over the child `Node`s of a given `Node` in the `Tree`. Each call to `next` will +/// return an immutable reference to the next child `Node`. +/// +pub struct Children<'a, T: 'a> { + tree: &'a Tree, + child_ids: Iter<'a, NodeId>, +} + +impl<'a, T> IteratorNew<'a, T, Children<'a, T>> for Children<'a, T> { + fn new(tree: &'a Tree, node_id: NodeId) -> Children<'a, T> { + Children { + tree: tree, + child_ids: tree.get_unsafe(&node_id).children().as_slice().iter(), + } + } +} + +impl<'a, T> Iterator for Children<'a, T> { + type Item = &'a Node; + + fn next(&mut self) -> Option<&'a Node> { + if let Some(ref next_child_id) = self.child_ids.next() { + return Some(self.tree.get_unsafe(next_child_id)); + } + None + } +} + +/// +/// An Iterator over the children of a `Node`. +/// +/// Iterates over `NodeId`s instead of over the `Node`s themselves. +/// +pub struct ChildrenIds<'a> { + child_ids: Iter<'a, NodeId>, +} + +impl<'a, T> IteratorNew<'a, T, ChildrenIds<'a>> for ChildrenIds<'a> { + fn new(tree: &'a Tree, node_id: NodeId) -> ChildrenIds<'a> { + ChildrenIds { child_ids: tree.get_unsafe(&node_id).children().as_slice().iter() } + } +} + +impl<'a> Iterator for ChildrenIds<'a> { + type Item = &'a NodeId; + + fn next(&mut self) -> Option<&'a NodeId> { + self.child_ids.next() + } +} + +/// +/// An Iterator over the sub-tree relative to a given `Node`. +/// +/// Iterates over all of the `Node`s in the sub-tree of a given `Node` in the `Tree`. Each call to +/// `next` will return an immutable reference to the next `Node` in Pre-Order Traversal order. +/// +pub struct PreOrderTraversal<'a, T: 'a> { + tree: &'a Tree, + data: VecDeque, +} + +impl<'a, T> IteratorNew<'a, T, PreOrderTraversal<'a, T>> for PreOrderTraversal<'a, T> { + fn new(tree: &'a Tree, node_id: NodeId) -> PreOrderTraversal { + + // over allocating, but all at once instead of re-sizing and re-allocating as we go + let mut data = VecDeque::with_capacity(tree.nodes.capacity()); + + data.push_front(node_id); + + PreOrderTraversal { + tree: tree, + data: data, + } + } +} + +impl<'a, T> Iterator for PreOrderTraversal<'a, T> { + type Item = &'a Node; + + fn next(&mut self) -> Option<&'a Node> { + let id = self.data.pop_front(); + + if let Some(ref node_id) = id { + let node_ref = self.tree.get_unsafe(node_id); + + // prepend child_ids + for child_id in node_ref.children().iter().rev() { + self.data.push_front(child_id.clone()); + } + + return Some(node_ref); + } + None + } +} + +/// +/// An Iterator over the sub-tree relative to a given `Node`. +/// +/// Iterates over all of the `Node`s in the sub-tree of a given `Node` in the `Tree`. Each call to +/// `next` will return an immutable reference to the next `Node` in Post-Order Traversal order. +/// +pub struct PostOrderTraversal<'a, T: 'a> { + tree: &'a Tree, + ids: IntoIter, +} + +impl<'a, T> PostOrderTraversal<'a, T> { + fn process_nodes(starting_id: NodeId, tree: &Tree, ids: &mut Vec) { + let node = tree.get_unsafe(&starting_id); + + for child_id in node.children() { + PostOrderTraversal::process_nodes(child_id.clone(), tree, ids); + } + + ids.push(starting_id); + } +} + +impl<'a, T> IteratorNew<'a, T, PostOrderTraversal<'a, T>> for PostOrderTraversal<'a, T> { + fn new(tree: &'a Tree, node_id: NodeId) -> PostOrderTraversal { + + // over allocating, but all at once instead of re-sizing and re-allocating as we go + let mut ids = Vec::with_capacity(tree.nodes.capacity()); + + PostOrderTraversal::process_nodes(node_id, tree, &mut ids); + + PostOrderTraversal { + tree: tree, + ids: ids.into_iter(), + } + } +} + +impl<'a, T> Iterator for PostOrderTraversal<'a, T> { + type Item = &'a Node; + + fn next(&mut self) -> Option<&'a Node> { + let id = self.ids.next(); + + if let Some(ref node_id) = id { + return Some(self.tree.get_unsafe(node_id)); + } + + None + } +} + +/// +/// An Iterator over the sub-tree relative to a given `Node`. +/// +/// Iterates over all of the `Node`s in the sub-tree of a given `Node` in the `Tree`. Each call to +/// `next` will return an immutable reference to the next `Node` in Level-Order Traversal order. +/// +pub struct LevelOrderTraversal<'a, T: 'a> { + tree: &'a Tree, + data: VecDeque, +} + +impl<'a, T> IteratorNew<'a, T, LevelOrderTraversal<'a, T>> for LevelOrderTraversal<'a, T> { + fn new(tree: &'a Tree, node_id: NodeId) -> LevelOrderTraversal { + + // over allocating, but all at once instead of re-sizing and re-allocating as we go + let mut data = VecDeque::with_capacity(tree.nodes.capacity()); + + data.push_back(node_id); + + LevelOrderTraversal { + tree: tree, + data: data, + } + } +} + +impl<'a, T> Iterator for LevelOrderTraversal<'a, T> { + type Item = &'a Node; + + fn next(&mut self) -> Option<&'a Node> { + let id = self.data.pop_front(); + + if let Some(ref node_id_ref) = id { + + let node_ref = self.tree.get_unsafe(node_id_ref); + + for child_id in node_ref.children() { + self.data.push_back(child_id.clone()); + } + + return Some(node_ref); + } + + None + } +} + +#[cfg(test)] +mod tests { + + use Tree; + use Node; + use InsertBehavior::*; + + #[test] + fn test_ancestors() { + let mut tree = Tree::new(); + + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let ancestors = tree.ancestors(&root_id).unwrap(); + assert_eq!(ancestors.count(), 0); + + let data = [0]; + for (index, node) in tree.ancestors(&node_1).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [1, 0]; + for (index, node) in tree.ancestors(&node_2).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [1, 0]; + for (index, node) in tree.ancestors(&node_3).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + } + + #[test] + fn test_ancestor_ids() { + let mut tree = Tree::new(); + + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let ancestor_ids = tree.ancestor_ids(&root_id).unwrap(); + assert_eq!(ancestor_ids.count(), 0); + + let data = [0]; + for (index, node_id) in tree.ancestor_ids(&node_1).unwrap().enumerate() { + assert_eq!(tree.get(node_id).unwrap().data(), &data[index]); + } + + let data = [1, 0]; + for (index, node_id) in tree.ancestor_ids(&node_2).unwrap().enumerate() { + assert_eq!(tree.get(node_id).unwrap().data(), &data[index]); + } + + let data = [1, 0]; + for (index, node_id) in tree.ancestor_ids(&node_3).unwrap().enumerate() { + assert_eq!(tree.get(node_id).unwrap().data(), &data[index]); + } + } + + #[test] + fn test_children() { + let mut tree = Tree::new(); + + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let data = [1]; + for (index, node) in tree.children(&root_id).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [2, 3]; + for (index, node) in tree.children(&node_1).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let children = tree.children(&node_2).unwrap(); + assert_eq!(children.count(), 0); + + let children = tree.children(&node_3).unwrap(); + assert_eq!(children.count(), 0); + } + + #[test] + fn test_children_ids() { + let mut tree = Tree::new(); + + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let data = [1]; + for (index, node_id) in tree.children_ids(&root_id).unwrap().enumerate() { + assert_eq!(tree.get(node_id).unwrap().data(), &data[index]); + } + + let data = [2, 3]; + for (index, node_id) in tree.children_ids(&node_1).unwrap().enumerate() { + assert_eq!(tree.get(node_id).unwrap().data(), &data[index]); + } + + let children_ids = tree.children_ids(&node_2).unwrap(); + assert_eq!(children_ids.count(), 0); + + let children_ids = tree.children_ids(&node_3).unwrap(); + assert_eq!(children_ids.count(), 0); + } + + #[test] + fn test_pre_order_traversal() { + let mut tree = Tree::new(); + + // 0 + // / \ + // 1 2 + // / + // 3 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let data = [0, 1, 3, 2]; + for (index, node) in tree.traverse_pre_order(&root_id).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [1, 3]; + for (index, node) in tree.traverse_pre_order(&node_1).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [2]; + for (index, node) in tree.traverse_pre_order(&node_2).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [3]; + for (index, node) in tree.traverse_pre_order(&node_3).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + } + + #[test] + fn test_post_order_traversal() { + let mut tree = Tree::new(); + + // 0 + // / \ + // 1 2 + // / + // 3 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let data = [3, 1, 2, 0]; + for (index, node) in tree.traverse_post_order(&root_id).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [3, 1]; + for (index, node) in tree.traverse_post_order(&node_1).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [2]; + for (index, node) in tree.traverse_post_order(&node_2).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [3]; + for (index, node) in tree.traverse_post_order(&node_3).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + } + + #[test] + fn test_level_order_traversal() { + let mut tree = Tree::new(); + + // 0 + // / \ + // 1 2 + // / + // 3 + let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + let node_2 = tree.insert(Node::new(2), UnderNode(&root_id)).unwrap(); + let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap(); + + let data = [0, 1, 2, 3]; + for (index, node) in tree.traverse_level_order(&root_id).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [1, 3]; + for (index, node) in tree.traverse_level_order(&node_1).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [2]; + for (index, node) in tree.traverse_level_order(&node_2).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + + let data = [3]; + for (index, node) in tree.traverse_level_order(&node_3).unwrap().enumerate() { + assert_eq!(node.data(), &data[index]); + } + } +} diff --git a/src/tree.rs b/src/tree/mod.rs similarity index 90% rename from src/tree.rs rename to src/tree/mod.rs index a3fbe74..467a23b 100644 --- a/src/tree.rs +++ b/src/tree/mod.rs @@ -1,14 +1,10 @@ +pub mod iterators; + use std::cmp::Ordering; -use super::behaviors::RemoveBehavior; -use super::behaviors::MoveBehavior; -use super::behaviors::InsertBehavior; -use super::behaviors::SwapBehavior; +use super::*; use super::snowflake::ProcessUniqueId; -use super::Node; -use super::NodeId; use super::MutableNode; -use super::NodeIdError; /// /// A `Tree` builder that provides more control over how a `Tree` is created. @@ -979,6 +975,227 @@ impl Tree { self.root.as_ref() } + /// + /// Returns an `Ancestors` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over the ancestor `Node`s of a given `NodeId` directly instead of having + /// to call `tree.get(...)` with a `NodeId` each time. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut ancestors = tree.ancestors(&node_1).unwrap(); + /// + /// assert_eq!(ancestors.next().unwrap().data(), &0); + /// assert!(ancestors.next().is_none()); + /// ``` + /// + pub fn ancestors(&self, node_id: &NodeId) -> Result, NodeIdError> { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::ancestors: Missing an error value but found an invalid NodeId.")); + } + + Ok(Ancestors::new(self, node_id.clone())) + } + + /// + /// Returns an `AncestorIds` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over the ancestor `NodeId`s of a given `NodeId`. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut ancestor_ids = tree.ancestor_ids(&node_1).unwrap(); + /// + /// assert_eq!(ancestor_ids.next().unwrap(), &root_id); + /// assert!(ancestor_ids.next().is_none()); + /// ``` + /// + pub fn ancestor_ids(&self, node_id: &NodeId) -> Result, NodeIdError> { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::ancestor_ids: Missing an error value but found an invalid NodeId.")); + } + + Ok(AncestorIds::new(self, node_id.clone())) + } + + /// + /// Returns a `Children` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over the child `Node`s of a given `NodeId` directly instead of having + /// to call `tree.get(...)` with a `NodeId` each time. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut children = tree.children(&root_id).unwrap(); + /// + /// assert_eq!(children.next().unwrap().data(), &1); + /// assert!(children.next().is_none()); + /// ``` + /// + pub fn children(&self, node_id: &NodeId) -> Result, NodeIdError> { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::children: Missing an error value but found an invalid NodeId.")); + } + + Ok(Children::new(self, node_id.clone())) + } + + /// + /// Returns a `ChildrenIds` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over the child `NodeId`s of a given `NodeId`. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut children_ids = tree.children_ids(&root_id).unwrap(); + /// + /// assert_eq!(children_ids.next().unwrap(), &node_1); + /// assert!(children_ids.next().is_none()); + /// ``` + /// + pub fn children_ids(&self, node_id: &NodeId) -> Result { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::children_ids: Missing an error value but found an invalid NodeId.")); + } + + Ok(ChildrenIds::new(self, node_id.clone())) + } + + /// Returns a `PreOrderTraversal` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over all of the `Node`s in the sub-tree below a given `Node`. This + /// iterator will always include that sub-tree "root" specified by the `NodeId` given. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut nodes = tree.traverse_pre_order(&root_id).unwrap(); + /// + /// assert_eq!(nodes.next().unwrap().data(), &0); + /// assert_eq!(nodes.next().unwrap().data(), &1); + /// assert!(nodes.next().is_none()); + /// ``` + /// + #[cfg_attr(rustfmt, rustfmt_skip)] + // todo: remove this if https://github.com/rust-lang-nursery/rustfmt/issues/1260 is resolved + pub fn traverse_pre_order(&self, node_id: &NodeId) + -> Result, NodeIdError> + { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::traverse_pre_order: Missing an error value but found an invalid NodeId.")); + } + + Ok(PreOrderTraversal::new(self, node_id.clone())) + } + + /// Returns a `PostOrderTraversal` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over all of the `Node`s in the sub-tree below a given `Node`. This + /// iterator will always include that sub-tree "root" specified by the `NodeId` given. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut nodes = tree.traverse_post_order(&root_id).unwrap(); + /// + /// assert_eq!(nodes.next().unwrap().data(), &1); + /// assert_eq!(nodes.next().unwrap().data(), &0); + /// assert!(nodes.next().is_none()); + /// ``` + /// + #[cfg_attr(rustfmt, rustfmt_skip)] + // todo: remove this if https://github.com/rust-lang-nursery/rustfmt/issues/1260 is resolved + pub fn traverse_post_order(&self, node_id: &NodeId) + -> Result, NodeIdError> + { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::traverse_post_order: Missing an error value but found an invalid NodeId.")); + } + + Ok(PostOrderTraversal::new(self, node_id.clone())) + } + + /// Returns a `LevelOrderTraversal` iterator (or a `NodeIdError` if one occurred). + /// + /// Allows iteration over all of the `Node`s in the sub-tree below a given `Node`. This + /// iterator will always include that sub-tree "root" specified by the `NodeId` given. + /// + /// ``` + /// use id_tree::*; + /// use id_tree::InsertBehavior::*; + /// + /// let mut tree: Tree = Tree::new(); + /// let root_id = tree.insert(Node::new(0), AsRoot).unwrap(); + /// let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap(); + /// + /// let mut nodes = tree.traverse_level_order(&root_id).unwrap(); + /// + /// assert_eq!(nodes.next().unwrap().data(), &0); + /// assert_eq!(nodes.next().unwrap().data(), &1); + /// assert!(nodes.next().is_none()); + /// ``` + /// + #[cfg_attr(rustfmt, rustfmt_skip)] + // todo: remove this if https://github.com/rust-lang-nursery/rustfmt/issues/1260 is resolved + pub fn traverse_level_order(&self, node_id: &NodeId) + -> Result, NodeIdError> + { + let (is_valid, error) = self.is_valid_node_id(node_id); + if !is_valid { + return Err(error.expect( + "Tree::traverse_level_order: Missing an error value but found an invalid NodeId.") + ); + } + + Ok(LevelOrderTraversal::new(self, node_id.clone())) + } + // Nothing should make it past this function. // If there is a way for a NodeId to be invalid, it should be caught here. fn is_valid_node_id(&self, node_id: &NodeId) -> (bool, Option) { @@ -1134,6 +1351,10 @@ impl Tree { } } +trait IteratorNew<'a, T, I> { + fn new(tree: &'a Tree, node_id: NodeId) -> I; +} + #[cfg(test)] mod tree_builder_tests { use super::TreeBuilder; diff --git a/tests/error_tests.rs b/tests/error_tests.rs index 6b9272e..34a5525 100644 --- a/tests/error_tests.rs +++ b/tests/error_tests.rs @@ -235,3 +235,131 @@ fn test_swap_sub_trees_of_different_trees() { let error = result.err().unwrap(); assert_eq!(error, NodeIdError::InvalidNodeIdForTree); } + +#[test] +fn test_ancestors_different_trees() { + let mut a = Tree::new(); + let b = Tree::::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + + // note usage of `b` instead of `a` + let ancestors = b.ancestors(&root_id); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::InvalidNodeIdForTree); +} + +#[test] +fn test_ancestors_old_id() { + let mut a = Tree::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + // `.clone()` required to get this error + let root_id_clone = root_id.clone(); + let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap(); + + // note usage of cloned `NodeId` + let ancestors = a.ancestors(&root_id_clone); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::NodeIdNoLongerValid); +} + +#[test] +fn test_ancestor_ids_different_trees() { + let mut a = Tree::new(); + let b = Tree::::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + + // note usage of `b` instead of `a` + let ancestors = b.ancestor_ids(&root_id); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::InvalidNodeIdForTree); +} + +#[test] +fn test_ancestor_ids_old_id() { + let mut a = Tree::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + // `.clone()` required to get this error + let root_id_clone = root_id.clone(); + let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap(); + + // note usage of cloned `NodeId` + let ancestors = a.ancestor_ids(&root_id_clone); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::NodeIdNoLongerValid); +} + +#[test] +fn test_children_different_trees() { + let mut a = Tree::new(); + let b = Tree::::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + + // note usage of `b` instead of `a` + let ancestors = b.children(&root_id); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::InvalidNodeIdForTree); +} + +#[test] +fn test_children_old_id() { + let mut a = Tree::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + // `.clone()` required to get this error + let root_id_clone = root_id.clone(); + let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap(); + + // note usage of cloned `NodeId` + let ancestors = a.children(&root_id_clone); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::NodeIdNoLongerValid); +} + +#[test] +fn test_children_ids_different_trees() { + let mut a = Tree::new(); + let b = Tree::::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + + // note usage of `b` instead of `a` + let ancestors = b.children_ids(&root_id); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::InvalidNodeIdForTree); +} + +#[test] +fn test_children_ids_old_id() { + let mut a = Tree::new(); + + let root_id = a.insert(Node::new(1), InsertBehavior::AsRoot).unwrap(); + // `.clone()` required to get this error + let root_id_clone = root_id.clone(); + let _ = a.remove_node(root_id, RemoveBehavior::DropChildren).unwrap(); + + // note usage of cloned `NodeId` + let ancestors = a.children_ids(&root_id_clone); + + assert!(ancestors.is_err()); + let error = ancestors.err().unwrap(); + assert_eq!(error, NodeIdError::NodeIdNoLongerValid); +}