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}