|
@@ -21,22 +21,41 @@ use std::{collections::VecDeque, iter::FusedIterator, mem};
|
|
|
#[cfg(test)]
|
|
#[cfg(test)]
|
|
|
mod tests;
|
|
mod tests;
|
|
|
|
|
|
|
|
-#[derive(Clone, Copy, Debug, PartialEq)]
|
|
|
|
|
|
|
+/// This struct represents a Leaf of a [`DarkTree`],
|
|
|
|
|
+/// holding this tree node data, along with positional
|
|
|
|
|
+/// indexes information, based on tree's traversal order.
|
|
|
|
|
+/// These indexes are only here to enable referencing
|
|
|
|
|
+/// connected nodes, and are *not* used as pointers by the
|
|
|
|
|
+/// tree. Creator must ensure they are properly setup.
|
|
|
|
|
+#[derive(Debug, PartialEq)]
|
|
|
struct DarkLeaf<T> {
|
|
struct DarkLeaf<T> {
|
|
|
/// Data holded by this leaf
|
|
/// Data holded by this leaf
|
|
|
data: T,
|
|
data: T,
|
|
|
|
|
+ /// Index showcasing this leaf's position, when all
|
|
|
|
|
+ /// leafs are in order.
|
|
|
|
|
+ index: usize,
|
|
|
/// Index showcasing this leaf's parent tree, when all
|
|
/// Index showcasing this leaf's parent tree, when all
|
|
|
- /// leafs are in order. None indicates this leaf has no
|
|
|
|
|
- /// parent.
|
|
|
|
|
|
|
+ /// leafs are in order. None indicates that this leaf
|
|
|
|
|
+ /// has no parent.
|
|
|
parent_index: Option<usize>,
|
|
parent_index: Option<usize>,
|
|
|
|
|
+ /// Vector of indexes showcasing this leaf's children
|
|
|
|
|
+ /// positions, when all leafs are in order. If vector
|
|
|
|
|
+ /// is empty, it indicates that this leaf has no children.
|
|
|
|
|
+ children_indexes: Vec<usize>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl<T> DarkLeaf<T> {
|
|
impl<T> DarkLeaf<T> {
|
|
|
|
|
+ /// Every leaf is initiated using default indexes.
|
|
|
fn new(data: T) -> DarkLeaf<T> {
|
|
fn new(data: T) -> DarkLeaf<T> {
|
|
|
- Self { data, parent_index: None }
|
|
|
|
|
|
|
+ Self { data, index: 0, parent_index: None, children_indexes: vec![] }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// This struct represents a Tree using DFS post-order traversal,
|
|
|
|
|
+/// where when we iterate through the tree, we first process tree
|
|
|
|
|
+/// node's children, and then the node itself, recursively.
|
|
|
|
|
+/// Based on this, initial tree node (leaf), known as the root,
|
|
|
|
|
+/// will always show up at the end of iteration.
|
|
|
#[derive(Debug, PartialEq)]
|
|
#[derive(Debug, PartialEq)]
|
|
|
struct DarkTree<T> {
|
|
struct DarkTree<T> {
|
|
|
/// This tree's leaf information, along with its data
|
|
/// This tree's leaf information, along with its data
|
|
@@ -46,20 +65,28 @@ struct DarkTree<T> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl<T> DarkTree<T> {
|
|
impl<T> DarkTree<T> {
|
|
|
|
|
+ /// Initialize a [`DarkTree`], using provided data to
|
|
|
|
|
+ /// generate its root.
|
|
|
fn new(data: T, children: Vec<DarkTree<T>>) -> DarkTree<T> {
|
|
fn new(data: T, children: Vec<DarkTree<T>>) -> DarkTree<T> {
|
|
|
let leaf = DarkLeaf::new(data);
|
|
let leaf = DarkLeaf::new(data);
|
|
|
Self { leaf, children }
|
|
Self { leaf, children }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// Immutably iterate through the tree, using DFS post-order
|
|
|
|
|
+ /// traversal.
|
|
|
fn iter(&self) -> DarkTreeIter<'_, T> {
|
|
fn iter(&self) -> DarkTreeIter<'_, T> {
|
|
|
DarkTreeIter { children: std::slice::from_ref(self), parent: None }
|
|
DarkTreeIter { children: std::slice::from_ref(self), parent: None }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// Mutably iterate through the tree, using DFS post-order
|
|
|
|
|
+ /// traversal.
|
|
|
fn iter_mut(&mut self) -> DarkTreeIterMut<'_, T> {
|
|
fn iter_mut(&mut self) -> DarkTreeIterMut<'_, T> {
|
|
|
DarkTreeIterMut { children: std::slice::from_mut(self), parent: None, parent_leaf: None }
|
|
DarkTreeIterMut { children: std::slice::from_mut(self), parent: None, parent_leaf: None }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Immutable iterator of a [`DarkTree`], performing DFS post-order
|
|
|
|
|
+/// traversal on the Tree leafs.
|
|
|
struct DarkTreeIter<'a, T> {
|
|
struct DarkTreeIter<'a, T> {
|
|
|
children: &'a [DarkTree<T>],
|
|
children: &'a [DarkTree<T>],
|
|
|
parent: Option<Box<DarkTreeIter<'a, T>>>,
|
|
parent: Option<Box<DarkTreeIter<'a, T>>>,
|
|
@@ -74,6 +101,10 @@ impl<T> Default for DarkTreeIter<'_, T> {
|
|
|
impl<'a, T> Iterator for DarkTreeIter<'a, T> {
|
|
impl<'a, T> Iterator for DarkTreeIter<'a, T> {
|
|
|
type Item = &'a DarkLeaf<T>;
|
|
type Item = &'a DarkLeaf<T>;
|
|
|
|
|
|
|
|
|
|
+ /// Grab next item iterator visits and return
|
|
|
|
|
+ /// its immutable reference, or recursively
|
|
|
|
|
+ /// create and continue iteration on current
|
|
|
|
|
+ /// leaf's children.
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
match self.children.first() {
|
|
match self.children.first() {
|
|
|
None => match self.parent.take() {
|
|
None => match self.parent.take() {
|
|
@@ -102,6 +133,10 @@ impl<'a, T> Iterator for DarkTreeIter<'a, T> {
|
|
|
|
|
|
|
|
impl<T> FusedIterator for DarkTreeIter<'_, T> {}
|
|
impl<T> FusedIterator for DarkTreeIter<'_, T> {}
|
|
|
|
|
|
|
|
|
|
+/// Define fusion iteration behavior, allowing
|
|
|
|
|
+/// us to use the [`DarkTreeIter`] iterator in
|
|
|
|
|
+/// loops directly, without using .iter() method
|
|
|
|
|
+/// of [`DarkTree`].
|
|
|
impl<'a, T> IntoIterator for &'a DarkTree<T> {
|
|
impl<'a, T> IntoIterator for &'a DarkTree<T> {
|
|
|
type Item = &'a DarkLeaf<T>;
|
|
type Item = &'a DarkLeaf<T>;
|
|
|
|
|
|
|
@@ -112,6 +147,8 @@ impl<'a, T> IntoIterator for &'a DarkTree<T> {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Mutable iterator of a [`DarkTree`], performing DFS post-order
|
|
|
|
|
+/// traversal on the Tree leafs.
|
|
|
struct DarkTreeIterMut<'a, T> {
|
|
struct DarkTreeIterMut<'a, T> {
|
|
|
children: &'a mut [DarkTree<T>],
|
|
children: &'a mut [DarkTree<T>],
|
|
|
parent: Option<Box<DarkTreeIterMut<'a, T>>>,
|
|
parent: Option<Box<DarkTreeIterMut<'a, T>>>,
|
|
@@ -127,6 +164,10 @@ impl<T> Default for DarkTreeIterMut<'_, T> {
|
|
|
impl<'a, T> Iterator for DarkTreeIterMut<'a, T> {
|
|
impl<'a, T> Iterator for DarkTreeIterMut<'a, T> {
|
|
|
type Item = &'a mut DarkLeaf<T>;
|
|
type Item = &'a mut DarkLeaf<T>;
|
|
|
|
|
|
|
|
|
|
+ /// Grab next item iterator visits and return
|
|
|
|
|
+ /// its mutable reference, or recursively
|
|
|
|
|
+ /// create and continue iteration on current
|
|
|
|
|
+ /// leaf's children.
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
let children = mem::take(&mut self.children);
|
|
let children = mem::take(&mut self.children);
|
|
|
match children.split_first_mut() {
|
|
match children.split_first_mut() {
|
|
@@ -155,6 +196,10 @@ impl<'a, T> Iterator for DarkTreeIterMut<'a, T> {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Define fusion iteration behavior, allowing
|
|
|
|
|
+/// us to use the [`DarkTreeIterMut`] iterator
|
|
|
|
|
+/// in loops directly, without using .iter_mut()
|
|
|
|
|
+/// method of [`DarkTree`].
|
|
|
impl<'a, T> IntoIterator for &'a mut DarkTree<T> {
|
|
impl<'a, T> IntoIterator for &'a mut DarkTree<T> {
|
|
|
type Item = &'a mut DarkLeaf<T>;
|
|
type Item = &'a mut DarkLeaf<T>;
|
|
|
|
|
|
|
@@ -165,6 +210,9 @@ impl<'a, T> IntoIterator for &'a mut DarkTree<T> {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Special iterator of a [`DarkTree`], performing DFS post-order
|
|
|
|
|
+/// traversal on the Tree leafs, consuming each leaf. Since this
|
|
|
|
|
+/// iterator consumes the tree, it becomes unusable after it's moved.
|
|
|
struct DarkTreeIntoIter<T> {
|
|
struct DarkTreeIntoIter<T> {
|
|
|
children: VecDeque<DarkTree<T>>,
|
|
children: VecDeque<DarkTree<T>>,
|
|
|
parent: Option<Box<DarkTreeIntoIter<T>>>,
|
|
parent: Option<Box<DarkTreeIntoIter<T>>>,
|
|
@@ -179,6 +227,15 @@ impl<T> Default for DarkTreeIntoIter<T> {
|
|
|
impl<T> Iterator for DarkTreeIntoIter<T> {
|
|
impl<T> Iterator for DarkTreeIntoIter<T> {
|
|
|
type Item = DarkLeaf<T>;
|
|
type Item = DarkLeaf<T>;
|
|
|
|
|
|
|
|
|
|
+ /// Grab next item iterator visits, and return
|
|
|
|
|
+ /// its mutable reference, or recursively
|
|
|
|
|
+ /// create and continue iteration on current
|
|
|
|
|
+ /// leaf's children.
|
|
|
|
|
+
|
|
|
|
|
+ /// Move next item iterator visits from the tree
|
|
|
|
|
+ /// to the iterator consumer, if it has no children.
|
|
|
|
|
+ /// Otherwise recursively create and continue iteration
|
|
|
|
|
+ /// on current leaf's children, and moving it after them.
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
match self.children.pop_front() {
|
|
match self.children.pop_front() {
|
|
|
None => match self.parent.take() {
|
|
None => match self.parent.take() {
|
|
@@ -210,6 +267,10 @@ impl<T> Iterator for DarkTreeIntoIter<T> {
|
|
|
|
|
|
|
|
impl<T> FusedIterator for DarkTreeIntoIter<T> {}
|
|
impl<T> FusedIterator for DarkTreeIntoIter<T> {}
|
|
|
|
|
|
|
|
|
|
+/// Define fusion iteration behavior, allowing
|
|
|
|
|
+/// us to use the [`DarkTreeIntoIter`] .into_iter()
|
|
|
|
|
+/// method, to consume the [`DarkTree`] and iterate
|
|
|
|
|
+/// over it.
|
|
|
impl<T> IntoIterator for DarkTree<T> {
|
|
impl<T> IntoIterator for DarkTree<T> {
|
|
|
type Item = DarkLeaf<T>;
|
|
type Item = DarkLeaf<T>;
|
|
|
|
|
|