orx_tree/traversal/
traverser_core.rs

1use super::{
2    OverData, OverMut,
3    enumeration::Enumeration,
4    over::{Over, OverItem},
5    over_mut::{OverItemInto, OverItemMut},
6};
7use crate::{
8    NodeMut, NodeMutOrientation, NodeRef, TreeVariant, memory::MemoryPolicy,
9    pinned_storage::PinnedStorage,
10};
11use orx_self_or::SoM;
12use orx_selfref_col::NodePtr;
13
14pub trait TraverserCore<O = OverData>: Sized
15where
16    O: Over,
17{
18    type Storage<V>: Default
19    where
20        V: TreeVariant;
21
22    fn storage_mut<V: TreeVariant>(&mut self) -> &mut Self::Storage<V>;
23
24    fn iter_ptr_with_storage<'a, V>(
25        node_ptr: NodePtr<V>,
26        storage: impl SoM<Self::Storage<V>>,
27    ) -> impl Iterator<Item = <O::Enumeration as Enumeration>::Item<NodePtr<V>>>
28    where
29        V: TreeVariant + 'a;
30
31    fn iter_with_storage<'a, V, M, P>(
32        node: &'a impl NodeRef<'a, V, M, P>,
33        storage: impl SoM<Self::Storage<V>>,
34    ) -> impl Iterator<Item = OverItem<'a, V, O, M, P>>
35    where
36        V: TreeVariant + 'a,
37        M: MemoryPolicy,
38        P: PinnedStorage;
39
40    /// Returns an iterator which yields all nodes including the `node` and all its descendants; i.e.,
41    /// all nodes of the subtree rooted at the given `node`.
42    ///
43    /// The order of visited nodes depends on the internal walk strategy of the traverser; depth-first and
44    /// breadth-first are the most well-known traversals.
45    ///
46    /// Typically, the `iter` call of a traverser does not require any memory allocation.
47    ///
48    /// # Yields
49    ///
50    /// The return value of the iterations depend on the second generic parameter of the traverser which implements
51    /// the [`Over`] trait. The following is the complete list of implementations and the corresponding item type
52    /// of the created iterators. For any `Over` implementation, the corresponding traverser can be created by using
53    /// the `Default::default()` function; however, it is often more convenient to use the [`Traversal`] type.
54    /// The last column of the table demonstrates how to create different traverser types; where the depth first or dfs
55    /// is replaceable with any available traversal strategy such as `bfs` or `post_order`.
56    ///
57    /// | Over | Yields | Depth First Example |
58    /// |---|---|---|
59    /// | [`OverData`] | &data | `Traversal.dfs()` |
60    /// | [`OverDepthData`] | (depth, &data) | `Traversal.dfs().with_depth()` |
61    /// | [`OverSiblingIdxData`] | (sibling_idx, &data) | `Traversal.dfs().with_sibling_idx()` |
62    /// | [`OverDepthSiblingIdxData`] | (depth, sibling_idx, &data) | `Traversal.with_depth().with_sibling_idx()` |
63    /// | [`OverNode`] | Node | `Traversal.dfs().over_nodes()` |
64    /// | [`OverDepthNode`] | (depth, Node) | `Traversal.dfs().over_nodes().with_depth()` |
65    /// | [`OverSiblingIdxNode`] | (sibling_idx, Node) | `Traversal.dfs().over_nodes().with_sibling_idx()` |
66    /// | [`OverDepthSiblingIdxNode`] | (depth, sibling_idx, Node) | `Traversal.dfs().over_nodes().with_depth().with_sibling_idx()` |
67    ///
68    /// [`Traversal`]: crate::traversal::Traversal
69    /// [`OverData`]: crate::traversal::OverData
70    /// [`OverDepthData`]: crate::traversal::OverDepthData
71    /// [`OverSiblingIdxData`]: crate::traversal::OverSiblingIdxData
72    /// [`OverDepthSiblingIdxData`]: crate::traversal::OverDepthSiblingIdxData
73    /// [`OverNode`]: crate::traversal::OverNode
74    /// [`OverDepthNode`]: crate::traversal::OverDepthNode
75    /// [`OverSiblingIdxNode`]: crate::traversal::OverSiblingIdxNode
76    /// [`OverDepthSiblingIdxNode`]: crate::traversal::OverDepthSiblingIdxNode
77    fn iter<'a, V, M, P>(
78        &'a mut self,
79        node: &'a impl NodeRef<'a, V, M, P>,
80    ) -> impl Iterator<Item = OverItem<'a, V, O, M, P>>
81    where
82        V: TreeVariant + 'a,
83        M: MemoryPolicy,
84        P: PinnedStorage;
85
86    fn iter_mut_with_storage<'a, V, M, P, MO>(
87        node_mut: &'a mut NodeMut<'a, V, M, P, MO>,
88        storage: impl SoM<Self::Storage<V>>,
89    ) -> impl Iterator<Item = OverItemMut<'a, V, O, M, P>>
90    where
91        V: TreeVariant + 'a,
92        M: MemoryPolicy,
93        P: PinnedStorage,
94        MO: NodeMutOrientation,
95        O: OverMut;
96
97    /// Returns a mutable iterator which yields all nodes including the `node` and all its descendants; i.e.,
98    /// all nodes of the subtree rooted at the given `node`.
99    ///
100    /// The order of visited nodes depends on the internal walk strategy of the traverser; depth-first and
101    /// breadth-first are the most well-known traversals.
102    ///
103    /// Typically, the `iter` or `iter_mut` or `into_iter` call of a traverser does not require any memory allocation.
104    ///
105    /// # Yields
106    ///
107    /// The return value of the iterations depend on the second generic parameter of the traverser which implements
108    /// the [`OverMut`] trait. The following is the complete list of implementations and the corresponding item type
109    /// of the created iterators. For any `Over` implementation, the corresponding traverser can be created by using
110    /// the `Default::default()` function; however, it is often more convenient to use the [`Traversal`] type.
111    /// The last column of the table demonstrates how to create different traverser types; where the depth first or dfs
112    /// is replaceable with any available traversal strategy such as `bfs` or `post_order`.
113    ///
114    /// | Over | Yields | Depth First Example |
115    /// |---|---|---|
116    /// | [`OverData`] | &mut data | `Traversal.dfs()` |
117    /// | [`OverDepthData`] | (depth, &mut data) | `Traversal.dfs().with_depth()` |
118    /// | [`OverSiblingIdxData`] | (sibling_idx, &mut data) | `Traversal.dfs().with_sibling_idx()` |
119    /// | [`OverDepthSiblingIdxData`] | (depth, sibling_idx, &mut data) | `Traversal.with_depth().with_sibling_idx()` |
120    ///
121    /// [`Traversal`]: crate::traversal::Traversal
122    /// [`OverMut`]: crate::traversal::OverMut
123    /// [`OverData`]: crate::traversal::OverData
124    /// [`OverDepthData`]: crate::traversal::OverDepthData
125    /// [`OverSiblingIdxData`]: crate::traversal::OverSiblingIdxData
126    /// [`OverDepthSiblingIdxData`]: crate::traversal::OverDepthSiblingIdxData
127    fn iter_mut<'a, V, M, P, MO>(
128        &'a mut self,
129        node: &'a mut NodeMut<'a, V, M, P, MO>,
130    ) -> impl Iterator<Item = OverItemMut<'a, V, O, M, P>>
131    where
132        V: TreeVariant + 'a,
133        M: MemoryPolicy,
134        P: PinnedStorage,
135        MO: NodeMutOrientation,
136        O: OverMut;
137
138    fn into_iter_with_storage<'a, V, M, P, MO>(
139        node_mut: NodeMut<'a, V, M, P, MO>,
140        storage: impl SoM<Self::Storage<V>>,
141    ) -> impl Iterator<Item = OverItemInto<'a, V, O>>
142    where
143        V: TreeVariant + 'a,
144        M: MemoryPolicy,
145        P: PinnedStorage,
146        MO: NodeMutOrientation,
147        O: Over;
148
149    /// Returns an iterator which:
150    ///
151    /// * traverses all nodes including the `node` and its descendants; i.e.,
152    ///   all nodes of the subtree rooted at the given `node`,
153    /// * removes the traversed nodes from the tree, and
154    /// * yields their values.
155    ///
156    /// Once the iterator is consumed, the tree will be missing the subtree rooted at the given `node`.
157    /// If the given node is the root of the tree, the tree will be empty after this call.
158    ///
159    /// The order of visited nodes depends on the internal walk strategy of the traverser; depth-first and
160    /// breadth-first are the most well-known traversals.
161    ///
162    /// Typically, the `iter` or `iter_mut` or `into_iter` call of a traverser does not require any memory allocation.
163    ///
164    /// # Yields
165    ///
166    /// The return value of the iterations depend on the second generic parameter of the traverser which implements
167    /// the [`OverMut`] trait. The following is the complete list of implementations and the corresponding item type
168    /// of the created iterators. For any `Over` implementation, the corresponding traverser can be created by using
169    /// the `Default::default()` function; however, it is often more convenient to use the [`Traversal`] type.
170    /// The last column of the table demonstrates how to create different traverser types; where the depth first or dfs
171    /// is replaceable with any available traversal strategy such as `bfs` or `post_order`.
172    ///
173    /// Importantly note that, since the created iterators remove the nodes from the tree, the "data" below represents
174    /// the owned data taken out of the corresponding node, and hence, out of the tree.
175    ///
176    /// | Over | Yields | Depth First Example |
177    /// |---|---|---|
178    /// | [`OverData`] | data | `Traversal.dfs()` |
179    /// | [`OverDepthData`] | (depth, data) | `Traversal.dfs().with_depth()` |
180    /// | [`OverSiblingIdxData`] | (sibling_idx, data) | `Traversal.dfs().with_sibling_idx()` |
181    /// | [`OverDepthSiblingIdxData`] | (depth, sibling_idx, data) | `Traversal.with_depth().with_sibling_idx()` |
182    ///
183    /// [`Traversal`]: crate::traversal::Traversal
184    /// [`OverMut`]: crate::traversal::OverMut
185    /// [`OverData`]: crate::traversal::OverData
186    /// [`OverDepthData`]: crate::traversal::OverDepthData
187    /// [`OverSiblingIdxData`]: crate::traversal::OverSiblingIdxData
188    /// [`OverDepthSiblingIdxData`]: crate::traversal::OverDepthSiblingIdxData
189    #[allow(clippy::wrong_self_convention)]
190    fn into_iter<'a, V, M, P, MO>(
191        &'a mut self,
192        node: NodeMut<'a, V, M, P, MO>,
193    ) -> impl Iterator<Item = OverItemInto<'a, V, O>>
194    where
195        V: TreeVariant + 'a,
196        M: MemoryPolicy,
197        P: PinnedStorage,
198        MO: NodeMutOrientation,
199        O: OverMut;
200
201    // provided
202
203    fn iter_ptr_with_owned_storage<'a, V>(
204        node_ptr: NodePtr<V>,
205    ) -> impl Iterator<Item = <O::Enumeration as Enumeration>::Item<NodePtr<V>>>
206    where
207        V: TreeVariant + 'a,
208    {
209        Self::iter_ptr_with_storage(node_ptr, Self::Storage::default())
210    }
211
212    fn iter_with_owned_storage<'a, V, M, P>(
213        node: &'a impl NodeRef<'a, V, M, P>,
214    ) -> impl Iterator<Item = OverItem<'a, V, O, M, P>>
215    where
216        V: TreeVariant + 'a,
217        M: MemoryPolicy,
218        P: PinnedStorage,
219    {
220        Self::iter_with_storage(node, Self::Storage::default())
221    }
222
223    fn iter_mut_with_owned_storage<'a, V, M, P, MO>(
224        node_mut: &'a mut NodeMut<'a, V, M, P, MO>,
225    ) -> impl Iterator<Item = OverItemMut<'a, V, O, M, P>>
226    where
227        V: TreeVariant + 'a,
228        M: MemoryPolicy,
229        P: PinnedStorage,
230        MO: NodeMutOrientation,
231        O: OverMut,
232    {
233        Self::iter_mut_with_storage(node_mut, Self::Storage::default())
234    }
235
236    fn into_iter_with_owned_storage<'a, V, M, P, MO>(
237        node_mut: NodeMut<'a, V, M, P, MO>,
238    ) -> impl Iterator<Item = OverItemInto<'a, V, O>>
239    where
240        V: TreeVariant + 'a,
241        M: MemoryPolicy,
242        P: PinnedStorage,
243        MO: NodeMutOrientation,
244        O: Over,
245    {
246        Self::into_iter_with_storage(node_mut, Self::Storage::default())
247    }
248}