orx_tree/traversal/
traverser.rs

1use super::{OverData, over::Over, traverser_core::TraverserCore};
2
3/// A tree traverser that creates iterators which walk over a given node and all of its descendants;
4/// i.e., over all nodes of the subtree rooted at the given node.
5///
6/// The order the nodes are traversed depend on the specific traverser implementation; some well known
7/// traversals are depth-first, breadth-first or post-order.
8///
9/// A traverser holds its temporary data, and therefore, it might be used to create as many iterators
10/// as needed without requiring additional allocation.
11///
12/// The following three kinds of node methods can be called with a traverser.
13///
14/// * [`walk_with`]
15///   * Creates an iterator over references.
16///   * `Iterator<Item = &V::Item>`
17///   * The tree remains unchanged.
18/// * [`walk_mut_with`]
19///   * Creates an iterator over mutable references.
20///   * `Iterator<Item = &mut V::Item>`
21///   * The data of the subtree rooted at the given node might be mutated.
22///   * However, the structure of the tree remains unchanged.
23/// * [`into_walk_with`]
24///   * Creates an iterator over owned values taken out of the nodes.
25///   * `Iterator<Item = V::Item>`
26///   * All nodes belonging to the subtree rooted at the given node will be removed.
27///   * Corresponding data of the removed nodes will be yield in the order of the traversal.
28///
29/// # Construction
30///
31/// A traverser can be created by its `new` or `default` method such as:
32///
33/// ```
34/// use orx_tree::{*, traversal::*};
35///
36/// let mut traverser = Dfs::default();
37/// let mut traverser = Bfs::default();
38/// let mut traverser = PostOrder::default();
39///
40/// // or traverser to iterate over different items
41/// let mut traverser = Dfs::<OverNode>::new(); // yields Node rather than data
42/// let mut traverser = Bfs::<OverDepthData>::new(); // yields (depth, data)
43/// let mut traverser = PostOrder::<OverDepthSiblingIdxData>::new(); // yields (depth, sibling_idx, data)
44/// ```
45///
46/// However, it is often more convenient to use the [`Traversal`] type to create the traverser instances;
47/// and transform them to yield different items if needed.
48///
49/// ```ignore
50/// use orx_tree::*;
51///
52/// let mut traverser = Traversal.dfs();
53/// let mut traverser = Traversal.bfs();
54/// let mut traverser = Traversal.post_order();
55///
56/// // or traverser to iterate over different items
57/// let mut traverser = Traversal.dfs().over_nodes(); // yields Node rather than data
58/// let mut traverser = Traversal.bfs().with_depth(); // yields (depth, data)
59/// let mut traverser = Traversal.post_order().with_depth().with_sibling_idx(); // yields (depth, sibling_idx, data)
60/// ```
61///
62/// # Iterating Over Different Values
63///
64/// For immutable walks, it is possible to iterate over [`Node`]s rather than node data.
65///
66/// Further, for all three iterator methods, it is possible to add either or both of:
67///
68/// * **depth** of the traversed node,
69/// * **sibling_idx** of the traversed node among its siblings
70///
71/// to node value which is either node data or the node itself.
72///
73/// The return value of the iterations depend on the second generic parameter of the traverser which implements
74/// the [`Over`] trait. The following is the complete list of implementations and the corresponding item type
75/// of the created iterators. For any `Over` implementation, the corresponding traverser can be created by using
76/// the `Default::default()` function; however, it is often more convenient to use the [`Traversal`] type.
77///
78/// The last column of the table demonstrates how to create different traverser types; where the depth first or dfs
79/// is replaceable with any available traversal strategy such as `bfs` or `post_order`.
80///
81/// Further, **D** refers to node data, which is:
82/// * `&V::Item` with `iter`,
83/// * `&mut V::Item` with `iter_mut`, and
84/// * `V::Item` with `into_iter`.
85///
86/// | Over | Yields | Depth First Example |
87/// |---|---|---|
88/// | [`OverData`] | D | `Traversal.dfs()` |
89/// | [`OverDepthData`] | (depth, D) | `Traversal.dfs().with_depth()` |
90/// | [`OverSiblingIdxData`] | (sibling_idx, D) | `Traversal.dfs().with_sibling_idx()` |
91/// | [`OverDepthSiblingIdxData`] | (depth, sibling_idx, D) | `Traversal.with_depth().with_sibling_idx()` |
92/// | [`OverNode`] | Node | `Traversal.dfs().over_nodes()` |
93/// | [`OverDepthNode`] | (depth, Node) | `Traversal.dfs().over_nodes().with_depth()` |
94/// | [`OverSiblingIdxNode`] | (sibling_idx, Node) | `Traversal.dfs().over_nodes().with_sibling_idx()` |
95/// | [`OverDepthSiblingIdxNode`] | (depth, sibling_idx, Node) | `Traversal.dfs().over_nodes().with_depth().with_sibling_idx()` |
96///
97/// [`walk_with`]: crate::NodeRef::walk_with
98/// [`walk_mut_with`]: crate::NodeMut::walk_mut_with
99/// [`into_walk_with`]: crate::NodeMut::into_walk_with
100/// [`Node`]: crate::Node
101/// [`Traversal`]: crate::traversal::Traversal
102/// [`Over`]: crate::traversal::Over
103/// [`OverData`]: crate::traversal::OverData
104/// [`OverDepthData`]: crate::traversal::OverDepthData
105/// [`OverSiblingIdxData`]: crate::traversal::OverSiblingIdxData
106/// [`OverDepthSiblingIdxData`]: crate::traversal::OverDepthSiblingIdxData
107/// [`OverNode`]: crate::traversal::OverNode
108/// [`OverDepthNode`]: crate::traversal::OverDepthNode
109/// [`OverSiblingIdxNode`]: crate::traversal::OverSiblingIdxNode
110/// [`OverDepthSiblingIdxNode`]: crate::traversal::OverDepthSiblingIdxNode
111pub trait Traverser<O = OverData>: TraverserCore<O>
112where
113    O: Over,
114{
115    /// Transformed version of the traverser from creating iterators over `O` to `O2`.
116    type IntoOver<O2>: TraverserCore<O2> + Traverser<O2>
117    where
118        O2: Over;
119
120    /// Creates a new traverser.
121    fn new() -> Self;
122
123    /// Consumes this traverser and returns a transformed version of it
124    /// which creates iterators over `O2` rather than `O2`.
125    fn transform_into<O2: Over>(self) -> Self::IntoOver<O2>;
126
127    /// Returns the transformed version of the traverser where it yields:
128    /// * data rather than [`Node`]
129    /// * (depth, data) rather than (depth, [`Node`])
130    /// * (depth, sibling_idx, data) rather than (depth, sibling_idx, [`Node`])
131    ///
132    /// [`Node`]: crate::Node
133    fn over_data(self) -> Self::IntoOver<O::IntoOverData> {
134        self.transform_into::<O::IntoOverData>()
135    }
136
137    /// Returns the transformed version of the traverser where it yields:
138    /// * [`Node`] rather than data
139    /// * (depth, [`Node`]) rather than (depth, data)
140    /// * (depth, sibling_idx, [`Node`]) rather than (depth, sibling_idx, data)
141    ///
142    /// [`Node`]: crate::Node
143    fn over_nodes(self) -> Self::IntoOver<O::IntoOverNode> {
144        self.transform_into::<O::IntoOverNode>()
145    }
146
147    /// Returns the transformed version of the traverser where it yields:
148    ///
149    /// * (depth, x) rather than x
150    /// * (depth, sibling_idx, x) rather than (sibling_idx, x)
151    ///
152    /// where x might data or [`Node`].
153    ///
154    /// [`Node`]: crate::Node
155    fn with_depth(self) -> Self::IntoOver<O::IntoWithDepth> {
156        self.transform_into::<O::IntoWithDepth>()
157    }
158
159    /// Returns the transformed version of the traverser where it yields:
160    ///
161    /// * (sibling_idx, x) rather than x
162    /// * (depth, sibling_idx, x) rather than (depth, x)
163    ///
164    /// where x might data or [`Node`].
165    ///
166    /// [`Node`]: crate::Node
167    fn with_sibling_idx(self) -> Self::IntoOver<O::IntoWithSiblingIdx> {
168        self.transform_into::<O::IntoWithSiblingIdx>()
169    }
170}