indextree/traverse.rs
1//! Iterators.
2
3#![allow(clippy::redundant_closure_call)]
4
5use crate::{Arena, Node, NodeId};
6
7#[derive(Clone)]
8struct Iter<'a, T> {
9 arena: &'a Arena<T>,
10 node: Option<NodeId>,
11}
12
13impl<'a, T> Iter<'a, T> {
14 fn new(arena: &'a Arena<T>, node: impl Into<Option<NodeId>>) -> Self {
15 let node = node.into();
16
17 Self { arena, node }
18 }
19}
20
21#[derive(Clone)]
22struct DoubleEndedIter<'a, T> {
23 arena: &'a Arena<T>,
24 head: Option<NodeId>,
25 tail: Option<NodeId>,
26}
27
28impl<'a, T> DoubleEndedIter<'a, T> {
29 fn new(
30 arena: &'a Arena<T>,
31 head: impl Into<Option<NodeId>>,
32 tail: impl Into<Option<NodeId>>,
33 ) -> Self {
34 let head = head.into();
35 let tail = tail.into();
36
37 Self { arena, head, tail }
38 }
39}
40
41macro_rules! new_iterator {
42 ($(#[$attr:meta])* $name:ident, inner = $inner:ident, new = $new:expr $(,)?) => {
43 $(#[$attr])*
44 #[repr(transparent)]
45 #[derive(Clone)]
46 pub struct $name<'a, T>($inner<'a, T>);
47
48 #[allow(deprecated)]
49 impl<'a, T> $name<'a, T> {
50 pub(crate) fn new(arena: &'a Arena<T>, node: NodeId) -> Self {
51 let new: fn(&'a Arena<T>, NodeId) -> $inner<'a, T> = $new;
52 Self(new(arena, node))
53 }
54 }
55 };
56 ($(#[$attr:meta])* $name:ident, new = $new:expr, next = $next:expr $(,)?) => {
57 new_iterator!(
58 $(#[$attr])*
59 $name,
60 inner = Iter,
61 new = $new,
62 );
63
64 #[allow(deprecated)]
65 impl<'a, T> Iterator for $name<'a, T> {
66 type Item = NodeId;
67
68 fn next(&mut self) -> Option<NodeId> {
69 let next: fn(&Node<T>) -> Option<NodeId> = $next;
70
71 let node = self.0.node.take()?;
72 self.0.node = next(&self.0.arena[node]);
73 Some(node)
74 }
75 }
76
77 #[allow(deprecated)]
78 impl<'a, T> core::iter::FusedIterator for $name<'a, T> {}
79 };
80 ($(#[$attr:meta])* $name:ident, new = $new:expr, next = $next:expr, next_back = $next_back:expr $(,)?) => {
81 new_iterator!(
82 $(#[$attr])*
83 $name,
84 inner = DoubleEndedIter,
85 new = $new,
86 );
87
88 #[allow(deprecated)]
89 impl<'a, T> Iterator for $name<'a, T> {
90 type Item = NodeId;
91
92 fn next(&mut self) -> Option<NodeId> {
93 match (self.0.head, self.0.tail) {
94 (Some(head), Some(tail)) if head == tail => {
95 let result = head;
96 self.0.head = None;
97 self.0.tail = None;
98 Some(result)
99 }
100 (Some(head), None) | (Some(head), Some(_)) => {
101 let next: fn(&Node<T>) -> Option<NodeId> = $next;
102
103 self.0.head = next(&self.0.arena[head]);
104 Some(head)
105 }
106 (None, Some(_)) | (None, None) => None,
107 }
108 }
109 }
110
111 #[allow(deprecated)]
112 impl<'a, T> ::core::iter::DoubleEndedIterator for $name<'a, T> {
113 fn next_back(&mut self) -> Option<Self::Item> {
114 match (self.0.head, self.0.tail) {
115 (Some(head), Some(tail)) if head == tail => {
116 let result = head;
117 self.0.head = None;
118 self.0.tail = None;
119 Some(result)
120 }
121 (None, Some(tail)) | (Some(_), Some(tail)) => {
122 let next_back: fn(&Node<T>) -> Option<NodeId> = $next_back;
123
124 self.0.tail = next_back(&self.0.arena[tail]);
125 Some(tail)
126 }
127 (Some(_), None)| (None, None) => None,
128 }
129 }
130 }
131 };
132 ($(#[$attr:meta])* $name:ident, next = $next:expr $(,)?) => {
133 new_iterator!(
134 $(#[$attr])*
135 $name,
136 new = |arena, node| Iter::new(arena, node),
137 next = $next,
138 );
139 };
140 ($(#[$attr:meta])* $name:ident, next = $next:expr, next_back = $next_back:expr $(,)?) => {
141 new_iterator!(
142 $(#[$attr])*
143 $name,
144 new = |arena, node| DoubleEndedIter::new(arena, node, None),
145 next = $next,
146 next_back = $next_back,
147 );
148 };
149}
150
151new_iterator!(
152 /// An iterator of the IDs of the ancestors of a given node.
153 Ancestors,
154 next = |node| node.parent,
155);
156
157new_iterator!(
158 /// An iterator of the IDs of the predecessors of a given node.
159 Predecessors,
160 next = |node| node.previous_sibling.or(node.parent),
161);
162
163new_iterator!(
164 /// An iterator of the IDs of the siblings before a given node.
165 PrecedingSiblings,
166 new = |arena, node| {
167 let first = arena
168 .get(node)
169 .unwrap()
170 .parent
171 .and_then(|parent_id| arena.get(parent_id))
172 .and_then(|parent| parent.first_child);
173
174 DoubleEndedIter::new(arena, node, first)
175 },
176 next = |head| head.previous_sibling,
177 next_back = |tail| tail.next_sibling,
178);
179
180new_iterator!(
181 /// An iterator of the IDs of the siblings after a given node.
182 FollowingSiblings,
183 new = |arena, node| {
184 let last = arena
185 .get(node)
186 .unwrap()
187 .parent
188 .and_then(|parent_id| arena.get(parent_id))
189 .and_then(|parent| parent.last_child);
190
191 DoubleEndedIter::new(arena, node, last)
192 },
193 next = |head| head.next_sibling,
194 next_back = |tail| tail.previous_sibling,
195);
196
197new_iterator!(
198 /// An iterator of the IDs of the children of a given node, in insertion order.
199 Children,
200 new = |arena, node| DoubleEndedIter::new(arena, arena[node].first_child, arena[node].last_child),
201 next = |node| node.next_sibling,
202 next_back = |tail| tail.previous_sibling,
203);
204
205new_iterator!(
206 #[deprecated(
207 since = "4.7.0",
208 note = "please, use Children::rev() instead if you want to iterate in reverse"
209 )]
210 /// An iterator of the IDs of the children of a given node, in reverse insertion order.
211 ReverseChildren,
212 new = |arena, node| Iter::new(arena, arena[node].last_child),
213 next = |node| node.previous_sibling,
214);
215
216#[derive(Clone)]
217/// An iterator of the IDs of a given node and its descendants, as a pre-order depth-first search where children are visited in insertion order.
218///
219/// i.e. node -> first child -> second child
220pub struct Descendants<'a, T>(Traverse<'a, T>);
221
222impl<'a, T> Descendants<'a, T> {
223 pub(crate) fn new(arena: &'a Arena<T>, current: NodeId) -> Self {
224 Self(Traverse::new(arena, current))
225 }
226}
227
228impl<T> Iterator for Descendants<'_, T> {
229 type Item = NodeId;
230
231 fn next(&mut self) -> Option<NodeId> {
232 self.0.find_map(|edge| match edge {
233 NodeEdge::Start(node) => Some(node),
234 NodeEdge::End(_) => None,
235 })
236 }
237}
238
239impl<T> core::iter::FusedIterator for Descendants<'_, T> {}
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242/// Indicator if the node is at a start or endpoint of the tree
243pub enum NodeEdge {
244 /// Indicates that start of a node that has children.
245 ///
246 /// Yielded by `Traverse::next()` before the node’s descendants. In HTML or
247 /// XML, this corresponds to an opening tag like `<div>`.
248 Start(NodeId),
249
250 /// Indicates that end of a node that has children.
251 ///
252 /// Yielded by `Traverse::next()` after the node’s descendants. In HTML or
253 /// XML, this corresponds to a closing tag like `</div>`
254 End(NodeId),
255}
256
257impl NodeEdge {
258 /// Returns the next `NodeEdge` to be returned by forward depth-first traversal.
259 ///
260 /// # Examples
261 ///
262 /// ```
263 /// # use indextree::{Arena, NodeEdge};
264 /// # let mut arena = Arena::new();
265 /// # let n1 = arena.new_node("1");
266 /// # let n1_1 = arena.new_node("1_1");
267 /// # n1.append(n1_1, &mut arena);
268 /// # let n1_1_1 = arena.new_node("1_1_1");
269 /// # n1_1.append(n1_1_1, &mut arena);
270 /// # let n1_2 = arena.new_node("1_2");
271 /// # n1.append(n1_2, &mut arena);
272 /// # let n1_3 = arena.new_node("1_3");
273 /// # n1.append(n1_3, &mut arena);
274 /// #
275 /// // arena
276 /// // `-- 1
277 /// // |-- 1_1
278 /// // | `-- 1_1_1
279 /// // |-- 1_2
280 /// // `-- 1_3
281 ///
282 /// let steps = std::iter::successors(
283 /// Some(NodeEdge::Start(n1)),
284 /// |current| current.next_traverse(&arena)
285 /// )
286 /// .collect::<Vec<_>>();
287 /// let traversed_by_iter = n1.traverse(&arena).collect::<Vec<_>>();
288 /// assert_eq!(
289 /// steps,
290 /// traversed_by_iter,
291 /// "repeated `.next_traverse()`s emit same events as `NodeId::traverse()` iterator"
292 /// );
293 /// ```
294 ///
295 /// `NodeEdge` itself does not borrow an arena, so you can modify the nodes
296 /// being traversed.
297 ///
298 /// ```
299 /// # use indextree::{Arena, NodeEdge};
300 /// # let mut arena = Arena::new();
301 /// # let n1 = arena.new_node("1".to_owned());
302 /// # let n1_1 = arena.new_node("1_1".to_owned());
303 /// # n1.append(n1_1, &mut arena);
304 /// # let n1_1_1 = arena.new_node("1_1_1".to_owned());
305 /// # n1_1.append(n1_1_1, &mut arena);
306 /// # let n1_2 = arena.new_node("1_2".to_owned());
307 /// # n1.append(n1_2, &mut arena);
308 /// # let n1_3 = arena.new_node("1_3".to_owned());
309 /// # n1.append(n1_3, &mut arena);
310 /// #
311 /// // arena: Arena<String>
312 /// // `-- 1
313 /// // |-- 1_1
314 /// // | `-- 1_1_1
315 /// // |-- 1_2
316 /// // `-- 1_3
317 ///
318 /// assert_eq!(*arena[n1].get(), "1");
319 /// assert_eq!(*arena[n1_1_1].get(), "1_1_1");
320 /// assert_eq!(*arena[n1_3].get(), "1_3");
321 ///
322 /// let mut next = Some(NodeEdge::Start(n1));
323 /// let mut count = 0;
324 /// while let Some(current) = next {
325 /// next = current.next_traverse(&arena);
326 /// let current = match current {
327 /// NodeEdge::Start(id) => id,
328 /// NodeEdge::End(_) => continue,
329 /// };
330 ///
331 /// arena[current].get_mut().push_str(&format!(" (count={})", count));
332 /// count += 1;
333 /// }
334 ///
335 /// assert_eq!(*arena[n1].get(), "1 (count=0)");
336 /// assert_eq!(*arena[n1_1_1].get(), "1_1_1 (count=2)");
337 /// assert_eq!(*arena[n1_3].get(), "1_3 (count=4)");
338 /// ```
339 #[must_use]
340 pub fn next_traverse<T>(self, arena: &Arena<T>) -> Option<Self> {
341 match self {
342 NodeEdge::Start(node) => match arena[node].first_child {
343 Some(first_child) => Some(NodeEdge::Start(first_child)),
344 None => Some(NodeEdge::End(node)),
345 },
346 NodeEdge::End(node) => {
347 let node = &arena[node];
348 match node.next_sibling {
349 Some(next_sibling) => Some(NodeEdge::Start(next_sibling)),
350 // `node.parent()` here can only be `None` if the tree has
351 // been modified during iteration, but silently stoping
352 // iteration seems a more sensible behavior than panicking.
353 None => node.parent.map(NodeEdge::End),
354 }
355 }
356 }
357 }
358
359 /// Returns the previous `NodeEdge` to be returned by forward depth-first traversal.
360 ///
361 /// # Examples
362 ///
363 /// ```
364 /// # use indextree::{Arena, NodeEdge};
365 /// # let mut arena = Arena::new();
366 /// # let n1 = arena.new_node("1");
367 /// # let n1_1 = arena.new_node("1_1");
368 /// # n1.append(n1_1, &mut arena);
369 /// # let n1_1_1 = arena.new_node("1_1_1");
370 /// # n1_1.append(n1_1_1, &mut arena);
371 /// # let n1_2 = arena.new_node("1_2");
372 /// # n1.append(n1_2, &mut arena);
373 /// # let n1_3 = arena.new_node("1_3");
374 /// # n1.append(n1_3, &mut arena);
375 /// #
376 /// // arena
377 /// // `-- 1
378 /// // |-- 1_1
379 /// // | `-- 1_1_1
380 /// // |-- 1_2
381 /// // `-- 1_3
382 ///
383 /// let steps = std::iter::successors(
384 /// Some(NodeEdge::End(n1)),
385 /// |current| current.prev_traverse(&arena)
386 /// )
387 /// .collect::<Vec<_>>();
388 /// let traversed_by_iter = n1.reverse_traverse(&arena).collect::<Vec<_>>();
389 /// assert_eq!(
390 /// steps,
391 /// traversed_by_iter,
392 /// "repeated `.prev_traverse()`s emit same events as \
393 /// `NodeId::reverse_traverse()` iterator"
394 /// );
395 /// ```
396 ///
397 /// `NodeEdge` itself does not borrow an arena, so you can modify the nodes
398 /// being traversed.
399 ///
400 /// ```
401 /// use indextree::{Arena, NodeEdge};
402 ///
403 /// # let mut arena = Arena::new();
404 /// # let n1 = arena.new_node("1".to_owned());
405 /// # let n1_1 = arena.new_node("1_1".to_owned());
406 /// # n1.append(n1_1, &mut arena);
407 /// # let n1_1_1 = arena.new_node("1_1_1".to_owned());
408 /// # n1_1.append(n1_1_1, &mut arena);
409 /// # let n1_2 = arena.new_node("1_2".to_owned());
410 /// # n1.append(n1_2, &mut arena);
411 /// # let n1_3 = arena.new_node("1_3".to_owned());
412 /// # n1.append(n1_3, &mut arena);
413 /// #
414 /// // arena: Arena<String>
415 /// // `-- 1
416 /// // |-- 1_1
417 /// // | `-- 1_1_1
418 /// // |-- 1_2
419 /// // `-- 1_3
420 ///
421 /// assert_eq!(*arena[n1_3].get(), "1_3");
422 /// assert_eq!(*arena[n1_1_1].get(), "1_1_1");
423 /// assert_eq!(*arena[n1].get(), "1");
424 ///
425 /// let mut next = Some(NodeEdge::End(n1_3));
426 /// let mut count = 0;
427 /// while let Some(current) = next {
428 /// next = current.prev_traverse(&arena);
429 /// let current = match current {
430 /// NodeEdge::Start(id) => id,
431 /// NodeEdge::End(_) => continue,
432 /// };
433 ///
434 /// arena[current].get_mut().push_str(&format!(" (count={})", count));
435 /// count += 1;
436 /// }
437 ///
438 /// assert_eq!(*arena[n1_3].get(), "1_3 (count=0)");
439 /// assert_eq!(*arena[n1_1_1].get(), "1_1_1 (count=2)");
440 /// assert_eq!(*arena[n1].get(), "1 (count=4)");
441 /// ```
442 #[must_use]
443 pub fn prev_traverse<T>(self, arena: &Arena<T>) -> Option<Self> {
444 match self {
445 NodeEdge::End(node) => match arena[node].last_child {
446 Some(last_child) => Some(NodeEdge::End(last_child)),
447 None => Some(NodeEdge::Start(node)),
448 },
449 NodeEdge::Start(node) => {
450 let node = &arena[node];
451 match node.previous_sibling {
452 Some(previous_sibling) => Some(NodeEdge::End(previous_sibling)),
453 // `node.parent()` here can only be `None` if the tree has
454 // been modified during iteration, but silently stopping
455 // iteration seems a more sensible behavior than panicking.
456 None => node.parent.map(NodeEdge::Start),
457 }
458 }
459 }
460 }
461}
462
463#[derive(Clone)]
464/// An iterator of the "sides" of a node visited during a depth-first pre-order traversal,
465/// where node sides are visited start to end and children are visited in insertion order.
466///
467/// i.e. node.start -> first child -> second child -> node.end
468pub struct Traverse<'a, T> {
469 arena: &'a Arena<T>,
470 root: NodeId,
471 next: Option<NodeEdge>,
472}
473
474impl<'a, T> Traverse<'a, T> {
475 pub(crate) fn new(arena: &'a Arena<T>, current: NodeId) -> Self {
476 Self {
477 arena,
478 root: current,
479 next: Some(NodeEdge::Start(current)),
480 }
481 }
482
483 /// Calculates the next node.
484 fn next_of_next(&self, next: NodeEdge) -> Option<NodeEdge> {
485 if next == NodeEdge::End(self.root) {
486 return None;
487 }
488 next.next_traverse(self.arena)
489 }
490
491 /// Returns a reference to the arena.
492 #[inline]
493 #[must_use]
494 pub(crate) fn arena(&self) -> &Arena<T> {
495 self.arena
496 }
497}
498
499impl<T> Iterator for Traverse<'_, T> {
500 type Item = NodeEdge;
501
502 fn next(&mut self) -> Option<NodeEdge> {
503 let next = self.next.take()?;
504 self.next = self.next_of_next(next);
505 Some(next)
506 }
507}
508
509impl<T> core::iter::FusedIterator for Traverse<'_, T> {}
510
511#[derive(Clone)]
512/// An iterator of the "sides" of a node visited during a depth-first pre-order traversal,
513/// where nodes are visited end to start and children are visited in reverse insertion order.
514///
515/// i.e. node.end -> second child -> first child -> node.start
516pub struct ReverseTraverse<'a, T> {
517 arena: &'a Arena<T>,
518 root: NodeId,
519 next: Option<NodeEdge>,
520}
521
522impl<'a, T> ReverseTraverse<'a, T> {
523 pub(crate) fn new(arena: &'a Arena<T>, current: NodeId) -> Self {
524 Self {
525 arena,
526 root: current,
527 next: Some(NodeEdge::End(current)),
528 }
529 }
530
531 /// Calculates the next node.
532 fn next_of_next(&self, next: NodeEdge) -> Option<NodeEdge> {
533 if next == NodeEdge::Start(self.root) {
534 return None;
535 }
536 next.prev_traverse(self.arena)
537 }
538}
539
540impl<T> Iterator for ReverseTraverse<'_, T> {
541 type Item = NodeEdge;
542
543 fn next(&mut self) -> Option<NodeEdge> {
544 let next = self.next.take()?;
545 self.next = self.next_of_next(next);
546 Some(next)
547 }
548}
549
550impl<T> core::iter::FusedIterator for ReverseTraverse<'_, T> {}