orx_tree/traversal/
traverser.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use super::{over::Over, traverser_core::TraverserCore, OverData};

/// A tree traverser that creates iterators which walk over a given node and all of its descendants;
/// i.e., over all nodes of the subtree rooted at the given node.
///
/// The order the nodes are traversed depend on the specific traverser implementation; some well known
/// traversals are depth-first, breadth-first or post-order.
///
/// A traverser holds its temporary data, and therefore, it might be used to create as many iterators
/// as needed without requiring additional allocation.
///
/// The following three kinds of node methods can be called with a traverser.
///
/// * [`walk_with`]
///   * Creates an iterator over references.
///   * `Iterator<Item = &V::Item>`
///   * The tree remains unchanged.
/// * [`walk_mut_with`]
///   * Creates an iterator over mutable references.
///   * `Iterator<Item = &mut V::Item>`
///   * The data of the subtree rooted at the given node might be mutated.
///   * However, the structure of the tree remains unchanged.
/// * [`into_walk_with`]
///   * Creates an iterator over owned values taken out of the nodes.
///   * `Iterator<Item = V::Item>`
///   * All nodes belonging to the subtree rooted at the given node will be removed.
///   * Corresponding data of the removed nodes will be yield in the order of the traversal.
///
/// # Construction
///
/// A traverser can be created by its `new` or `default` method such as:
///
/// ```
/// use orx_tree::{*, traversal::*};
///
/// let mut traverser = Dfs::default();
/// let mut traverser = Bfs::default();
/// let mut traverser = PostOrder::default();
///
/// // or traverser to iterate over different items
/// let mut traverser = Dfs::<OverNode>::new(); // yields Node rather than data
/// let mut traverser = Bfs::<OverDepthData>::new(); // yields (depth, data)
/// let mut traverser = PostOrder::<OverDepthSiblingIdxData>::new(); // yields (depth, sibling_idx, data)
/// ```
///
/// However, it is often more convenient to use the [`Traversal`] type to create the traverser instances;
/// and transform them to yield different items if needed.
///
/// ```ignore
/// use orx_tree::*;
///
/// let mut traverser = Traversal.dfs();
/// let mut traverser = Traversal.bfs();
/// let mut traverser = Traversal.post_order();
///
/// // or traverser to iterate over different items
/// let mut traverser = Traversal.dfs().over_nodes(); // yields Node rather than data
/// let mut traverser = Traversal.bfs().with_depth(); // yields (depth, data)
/// let mut traverser = Traversal.post_order().with_depth().with_sibling_idx(); // yields (depth, sibling_idx, data)
/// ```
///
/// # Iterating Over Different Values
///
/// For immutable walks, it is possible to iterate over [`Node`]s rather than node data.
///
/// Further, for all three iterator methods, it is possible to add either or both of:
///
/// * **depth** of the traversed node,
/// * **sibling_idx** of the traversed node among its siblings
///
/// to node value which is either node data or the node itself.
///
/// The return value of the iterations depend on the second generic parameter of the traverser which implements
/// the [`Over`] trait. The following is the complete list of implementations and the corresponding item type
/// of the created iterators. For any `Over` implementation, the corresponding traverser can be created by using
/// the `Default::default()` function; however, it is often more convenient to use the [`Traversal`] type.
///
/// The last column of the table demonstrates how to create different traverser types; where the depth first or dfs
/// is replaceable with any available traversal strategy such as `bfs` or `post_order`.
///
/// Further, **D** refers to node data, which is:
/// * `&V::Item` with `iter`,
/// * `&mut V::Item` with `iter_mut`, and
/// * `V::Item` with `into_iter`.
///
/// | Over | Yields | Depth First Example |
/// |---|---|---|
/// | [`OverData`] | D | `Traversal.dfs()` |
/// | [`OverDepthData`] | (depth, D) | `Traversal.dfs().with_depth()` |
/// | [`OverSiblingIdxData`] | (sibling_idx, D) | `Traversal.dfs().with_sibling_idx()` |
/// | [`OverDepthSiblingIdxData`] | (depth, sibling_idx, D) | `Traversal.with_depth().with_sibling_idx()` |
/// | [`OverNode`] | Node | `Traversal.dfs().over_nodes()` |
/// | [`OverDepthNode`] | (depth, Node) | `Traversal.dfs().over_nodes().with_depth()` |
/// | [`OverSiblingIdxNode`] | (sibling_idx, Node) | `Traversal.dfs().over_nodes().with_sibling_idx()` |
/// | [`OverDepthSiblingIdxNode`] | (depth, sibling_idx, Node) | `Traversal.dfs().over_nodes().with_depth().with_sibling_idx()` |
///
/// [`walk_with`]: crate::NodeRef::walk_with
/// [`walk_mut_with`]: crate::NodeMut::walk_mut_with
/// [`into_walk_with`]: crate::NodeMut::into_walk_with
/// [`Node`]: crate::Node
/// [`Traversal`]: crate::traversal::Traversal
/// [`Over`]: crate::traversal::Over
/// [`OverData`]: crate::traversal::OverData
/// [`OverDepthData`]: crate::traversal::OverDepthData
/// [`OverSiblingIdxData`]: crate::traversal::OverSiblingIdxData
/// [`OverDepthSiblingIdxData`]: crate::traversal::OverDepthSiblingIdxData
/// [`OverNode`]: crate::traversal::OverNode
/// [`OverDepthNode`]: crate::traversal::OverDepthNode
/// [`OverSiblingIdxNode`]: crate::traversal::OverSiblingIdxNode
/// [`OverDepthSiblingIdxNode`]: crate::traversal::OverDepthSiblingIdxNode
pub trait Traverser<O = OverData>: TraverserCore<O>
where
    O: Over,
{
    /// Transformed version of the traverser from creating iterators over `O` to `O2`.
    type IntoOver<O2>: TraverserCore<O2> + Traverser<O2>
    where
        O2: Over;

    /// Creates a new traverser.
    fn new() -> Self;

    /// Consumes this traverser and returns a transformed version of it
    /// which creates iterators over `O2` rather than `O2`.
    fn transform_into<O2: Over>(self) -> Self::IntoOver<O2>;

    /// Returns the transformed version of the traverser where it yields:
    /// * data rather than [`Node`]
    /// * (depth, data) rather than (depth, [`Node`])
    /// * (depth, sibling_idx, data) rather than (depth, sibling_idx, [`Node`])
    ///
    /// [`Node`]: crate::Node
    fn over_data(self) -> Self::IntoOver<O::IntoOverData> {
        self.transform_into::<O::IntoOverData>()
    }

    /// Returns the transformed version of the traverser where it yields:
    /// * [`Node`] rather than data
    /// * (depth, [`Node`]) rather than (depth, data)
    /// * (depth, sibling_idx, [`Node`]) rather than (depth, sibling_idx, data)
    ///
    /// [`Node`]: crate::Node
    fn over_nodes(self) -> Self::IntoOver<O::IntoOverNode> {
        self.transform_into::<O::IntoOverNode>()
    }

    /// Returns the transformed version of the traverser where it yields:
    ///
    /// * (depth, x) rather than x
    /// * (depth, sibling_idx, x) rather than (sibling_idx, x)
    ///
    /// where x might data or [`Node`].
    ///
    /// [`Node`]: crate::Node
    fn with_depth(self) -> Self::IntoOver<O::IntoWithDepth> {
        self.transform_into::<O::IntoWithDepth>()
    }

    /// Returns the transformed version of the traverser where it yields:
    ///
    /// * (sibling_idx, x) rather than x
    /// * (depth, sibling_idx, x) rather than (depth, x)
    ///
    /// where x might data or [`Node`].
    ///
    /// [`Node`]: crate::Node
    fn with_sibling_idx(self) -> Self::IntoOver<O::IntoWithSiblingIdx> {
        self.transform_into::<O::IntoWithSiblingIdx>()
    }
}