瀏覽代碼

script/research/dark-forest: document everything

aggstam 2 年之前
父節點
當前提交
5101709f1c
共有 2 個文件被更改,包括 103 次插入4 次删除
  1. 65 4
      script/research/dark-forest/src/lib.rs
  2. 38 0
      script/research/dark-forest/src/tests.rs

+ 65 - 4
script/research/dark-forest/src/lib.rs

@@ -21,22 +21,41 @@ use std::{collections::VecDeque, iter::FusedIterator, mem};
 #[cfg(test)]
 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> {
     /// Data holded by this leaf
     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
-    /// 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>,
+    /// 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> {
+    /// Every leaf is initiated using default indexes.
     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)]
 struct DarkTree<T> {
     /// This tree's leaf information, along with its data
@@ -46,20 +65,28 @@ struct 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> {
         let leaf = DarkLeaf::new(data);
         Self { leaf, children }
     }
 
+    /// Immutably iterate through the tree, using DFS post-order
+    /// traversal.
     fn iter(&self) -> DarkTreeIter<'_, T> {
         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> {
         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> {
     children: &'a [DarkTree<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> {
     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> {
         match self.children.first() {
             None => match self.parent.take() {
@@ -102,6 +133,10 @@ impl<'a, T> Iterator for DarkTreeIter<'a, 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> {
     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> {
     children: &'a mut [DarkTree<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> {
     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> {
         let children = mem::take(&mut self.children);
         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> {
     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> {
     children: VecDeque<DarkTree<T>>,
     parent: Option<Box<DarkTreeIntoIter<T>>>,
@@ -179,6 +227,15 @@ impl<T> Default for DarkTreeIntoIter<T> {
 impl<T> Iterator for DarkTreeIntoIter<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> {
         match self.children.pop_front() {
             None => match self.parent.take() {
@@ -210,6 +267,10 @@ impl<T> Iterator 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> {
     type Item = DarkLeaf<T>;
 

+ 38 - 0
script/research/dark-forest/src/tests.rs

@@ -18,6 +18,8 @@
 
 use crate::DarkTree;
 
+/// Gereate a predefined [`DarkTree`] along with its
+/// expected traversal order.
 fn generate_tree() -> (DarkTree<i32>, Vec<i32>) {
     let tree = DarkTree::new(
         5,
@@ -36,9 +38,17 @@ fn generate_tree() -> (DarkTree<i32>, Vec<i32>) {
 pub fn test_darktree_iterator() {
     let (tree, traversal_order) = generate_tree();
 
+    // Use [`DarkTree`] iterator to collect current
+    // data, in order
     let nums: Vec<i32> = tree.iter().map(|x| x.data).collect();
 
+    // Verify iterator collected the data in the expected
+    // traversal order.
     assert_eq!(nums, traversal_order);
+
+    // Verify using iterator indexing methods to retrieve
+    // data from it, returns the expected one, as per
+    // expected traversal order.
     assert_eq!(tree.iter().nth(1).unwrap().data, traversal_order[1]);
 }
 
@@ -46,26 +56,46 @@ pub fn test_darktree_iterator() {
 fn test_darktree_traversal_order() {
     let (mut tree, traversal_order) = generate_tree();
 
+    // Loop using the fusion immutable iterator,
+    // verifying we grab the correct [`DarkLeaf`]
+    // immutable reference, as per expected
+    // traversal order.
     let mut index = 0;
     for leaf in &tree {
         assert_eq!(leaf.data, traversal_order[index]);
         index += 1;
     }
 
+    // Loop using the fusion mutable iterator,
+    // verifying we grab the correct [`DarkLeaf`]
+    // mutable reference, as per expected traversal
+    // order.
     index = 0;
     for leaf in &mut tree {
         assert_eq!(leaf.data, traversal_order[index]);
         index += 1;
     }
 
+    // Loop using [`DarkTree`] .iter_mut() mutable
+    // iterator, verifying we grab the correct [`DarkLeaf`]
+    // mutable reference, as per expected traversal
+    // order.
     for (index, leaf) in tree.iter_mut().enumerate() {
         assert_eq!(leaf.data, traversal_order[index]);
     }
 
+    // Loop using [`DarkTree`] .iter() immutable
+    // iterator, verifying we grab the correct [`DarkLeaf`]
+    // immutable reference, as per expected traversal
+    // order.
     for (index, leaf) in tree.iter().enumerate() {
         assert_eq!(leaf.data, traversal_order[index]);
     }
 
+    // Loop using [`DarkTree`] .into_iter() iterator,
+    // which consumes (moves) the tree, verifying we
+    // collect the correct [`DarkLeaf`], as per expected
+    // traversal order.
     for (index, leaf) in tree.into_iter().enumerate() {
         assert_eq!(leaf.data, traversal_order[index]);
     }
@@ -75,14 +105,22 @@ fn test_darktree_traversal_order() {
 fn test_darktree_mut_iterator() {
     let (mut tree, _) = generate_tree();
 
+    // Loop using [`DarkTree`] .iter_mut() mutable
+    // iterator, grabing a mutable reference over a
+    // [`DarkLeaf`], and mutating its inner data.
     for leaf in tree.iter_mut() {
         leaf.data += 1;
     }
 
+    // Loop using the fusion mutable iterator,
+    // grabing a mutable reference over a
+    // [`DarkLeaf`], and mutating its inner data.
     for leaf in &mut tree {
         leaf.data += 1;
     }
 
+    // Verify performed mutation actually happened
+    // on original tree.
     assert_eq!(
         tree,
         DarkTree::new(