generational_arena_tree/
iter.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use std::{collections::VecDeque, iter::FusedIterator};
6
7use crate::{sealed::Idx, Arena, BaseNode, BranchNode, LinkedNode, Node};
8
9/// An iterator over the [tokens] of a [node]'s [ancestors].
10///
11/// This iterator is returned by [`Node::ancestors`].
12///
13/// [tokens]: Node::Token
14/// [node]: Node
15/// [ancestors]: Node::ancestors
16///
17/// [`Node::ancestors`]: Node::ancestors
18#[must_use = "iterators are lazy and do nothing unless consumed"]
19pub struct Ancestors<'arena, Base: BaseNode> {
20	arena: &'arena Arena<Base>,
21
22	parent: Option<<<Base as BaseNode>::Branch as Node>::Token>,
23}
24
25/// An iterator over the [tokens] of a [branch]'s [children].
26///
27/// This iterator is returned by [`Branch::children`].
28///
29/// [tokens]: Node::Token
30/// [branch]: BranchNode
31/// [children]: Branch::children
32#[must_use = "iterators are lazy and do nothing unless consumed"]
33pub struct ChildrenLinked<'arena, Branch: BranchNode>
34where
35	Branch::Base: LinkedNode,
36{
37	arena: &'arena Arena<Branch::Base>,
38
39	child_front: Option<<Branch::Base as Node>::Token>,
40	child_back: Option<<Branch::Base as Node>::Token>,
41}
42
43/// An iterator over the [tokens] of a [branch]'s [descendants].
44///
45/// This iterator is returned by [`Branch::descendants`].
46///
47/// [tokens]: Node::Token
48/// [branch]: BranchNode
49/// [descendants]: Branch::descendants
50#[must_use = "iterators are lazy and do nothing unless consumed"]
51pub struct Descendants<'arena, Branch: BranchNode + 'arena>
52where
53	for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
54{
55	arena: &'arena Arena<Branch::Base>,
56
57	current: Option<Branch::ChildrenIter<'arena>>,
58	stack: VecDeque<Branch::ChildrenIter<'arena>>,
59}
60
61/// An iterator over the [tokens] of a [node]'s [preceding siblings].
62///
63/// This iterator is returned by [`LinkedNode::preceding_siblings`].
64///
65/// [tokens]: Node::Token
66/// [node]: LinkedNode
67/// [preceding siblings]: LinkedNode::preceding_siblings
68#[must_use = "iterators are lazy and do nothing unless consumed"]
69pub struct PrecedingSiblings<'arena, Linked: Node>
70where
71	Linked::Base: LinkedNode,
72{
73	arena: &'arena Arena<Linked::Base>,
74
75	prev: Option<<Linked::Base as Node>::Token>,
76}
77
78/// An iterator over the [tokens] of a [node]'s [following siblings].
79///
80/// This iterator is returned by [`LinkedNode::following_siblings`].
81///
82/// [tokens]: Node::Token
83/// [node]: LinkedNode
84/// [following siblings]: LinkedNode::following_siblings
85#[must_use = "iterators are lazy and do nothing unless consumed"]
86pub struct FollowingSiblings<'arena, Linked: Node>
87where
88	Linked::Base: LinkedNode,
89{
90	arena: &'arena Arena<Linked::Base>,
91
92	next: Option<<Linked::Base as Node>::Token>,
93}
94
95impl<'arena, Base: BaseNode> Ancestors<'arena, Base> {
96	#[inline(always)]
97	pub(super) const fn new(
98		arena: &'arena Arena<Base>,
99		parent: Option<<<Base as BaseNode>::Branch as Node>::Token>,
100	) -> Self {
101		Self { arena, parent }
102	}
103}
104
105impl<'arena, Base: BaseNode> Iterator for Ancestors<'arena, Base> {
106	type Item = <<Base as BaseNode>::Branch as Node>::Token;
107
108	#[inline]
109	fn next(&mut self) -> Option<Self::Item> {
110		self.parent.map(|parent| {
111			self.parent = self.arena.0[parent.idx()].parent();
112
113			parent
114		})
115	}
116
117	#[inline(always)]
118	fn size_hint(&self) -> (usize, Option<usize>) {
119		match &self.parent {
120			None => (0, Some(0)),
121			Some(_) => (1, None),
122		}
123	}
124}
125
126impl<'arena, Base: BaseNode> FusedIterator for Ancestors<'arena, Base> {}
127
128impl<'arena, Branch> ChildrenLinked<'arena, Branch>
129where
130	Branch: BranchNode,
131	Branch::Base: LinkedNode,
132{
133	#[inline(always)]
134	pub(super) const fn new(
135		arena: &'arena Arena<Branch::Base>,
136		child_front: Option<<Branch::Base as Node>::Token>,
137		child_back: Option<<Branch::Base as Node>::Token>,
138	) -> Self {
139		Self {
140			arena,
141
142			child_front,
143			child_back,
144		}
145	}
146}
147
148impl<'arena, Branch> Descendants<'arena, Branch>
149where
150	Branch: BranchNode + 'arena,
151	for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
152{
153	#[inline(always)]
154	pub(super) fn new(branch: &'arena Branch, arena: &'arena Arena<Branch::Base>) -> Self {
155		Self {
156			arena,
157
158			current: Some(branch.children(arena)),
159			stack: VecDeque::new(),
160		}
161	}
162}
163
164impl<'arena, Linked: Node> PrecedingSiblings<'arena, Linked>
165where
166	Linked::Base: LinkedNode,
167{
168	#[inline(always)]
169	pub(super) const fn new(arena: &'arena Arena<Linked::Base>, prev: Option<<Linked::Base as Node>::Token>) -> Self {
170		Self { arena, prev }
171	}
172}
173
174impl<'arena, Linked: Node> FollowingSiblings<'arena, Linked>
175where
176	Linked::Base: LinkedNode,
177{
178	#[inline(always)]
179	pub(super) const fn new(arena: &'arena Arena<Linked::Base>, next: Option<<Linked::Base as Node>::Token>) -> Self {
180		Self { arena, next }
181	}
182}
183
184impl<'arena, Branch> Iterator for ChildrenLinked<'arena, Branch>
185where
186	Branch: BranchNode,
187	Branch::Base: LinkedNode,
188{
189	type Item = <Branch::Base as Node>::Token;
190
191	fn next(&mut self) -> Option<Self::Item> {
192		self.child_front.map(|child| {
193			match self.child_back {
194				// If the front and back children have met in the middle, end both iterators.
195				Some(back) if child == back => {
196					(self.child_front, self.child_back) = (None, None);
197				},
198
199				// Otherwise, advance the front child forward.
200				_ => self.child_front = self.arena.0[child.idx()].next(),
201			}
202
203			child
204		})
205	}
206
207	fn size_hint(&self) -> (usize, Option<usize>) {
208		match (&self.child_front, &self.child_back) {
209			// No more items.
210			(None, None) => (0, Some(0)),
211			// 1 more item.
212			(Some(front), Some(back)) if front == back => (1, Some(1)),
213			// 2 or more items.
214			(Some(_), Some(_)) => (2, None),
215
216			// This _should_ be illegal state, but if it somehow does occur, then we don't have a
217			// proper size hint.
218			(..) => (0, None),
219		}
220	}
221}
222
223impl<'arena, Branch> DoubleEndedIterator for ChildrenLinked<'arena, Branch>
224where
225	Branch: BranchNode,
226	Branch::Base: LinkedNode,
227{
228	fn next_back(&mut self) -> Option<Self::Item> {
229		self.child_back.map(|child| {
230			match self.child_front {
231				// If the front and back children have met in the middle, end both iterators.
232				Some(front) if child == front => {
233					(self.child_front, self.child_back) = (None, None);
234				},
235
236				// Otherwise, advance the back child backward.
237				_ => self.child_back = self.arena.0[child.idx()].prev(),
238			}
239
240			child
241		})
242	}
243}
244
245impl<'arena, Branch> FusedIterator for ChildrenLinked<'arena, Branch>
246where
247	Branch: BranchNode,
248	Branch::Base: LinkedNode,
249{
250}
251
252impl<'arena, Branch> Iterator for Descendants<'arena, Branch>
253where
254	Branch: BranchNode + 'arena,
255	for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
256{
257	type Item = <Branch::Base as Node>::Token;
258
259	fn next(&mut self) -> Option<Self::Item> {
260		// Next descendant's token.
261		let token = match &mut self.current {
262			None => None,
263
264			Some(iter) => match iter.next() {
265				// If `current` has another token, use that.
266				Some(token) => Some(token),
267
268				// If `current` doesn't have another token, try to find a `ChildrenIter` in the stack
269				// that does.
270				None => {
271					self.current = None;
272					let mut token = None;
273
274					// Find the first `ChildrenIter` in the stack that has at least one child.
275					//
276					// NOTE: Going through multiple options to try to find a `ChildrenIter` in the stack
277					//     : that has at least one child, rather than trying next `next()` call, is
278					//     : required to ensure that this is a `FusedIterator`.
279					while let Some(mut iter) = self.stack.pop_front() {
280						match iter.next() {
281							// This `ChildrenIter` has at least one child: update `self.current` and use
282							// that child.
283							Some(child) => {
284								self.current = Some(iter);
285								token = Some(child);
286
287								break;
288							},
289
290							// This `ChildrenIter` does not have at least one child: move on to the next
291							// one.
292							None => continue,
293						}
294					}
295
296					token
297				},
298			},
299		};
300
301		// If there is a next token, and that token refers to a branch, add that branch's
302		// `ChildrenIter` to the stack.
303		if let Some(branch) = token
304			.as_ref()
305			.and_then(|token| <&Branch as TryFrom<&Branch::Base>>::try_from(&self.arena.0[token.idx()]).ok())
306		{
307			self.stack.push_back(branch.children(self.arena));
308		}
309
310		token
311	}
312
313	fn size_hint(&self) -> (usize, Option<usize>) {
314		match &self.current {
315			// There are no more children iterators to iterate, and so no more descendants are
316			// possible.
317			None => (0, Some(0)),
318
319			Some(iter) => {
320				let (min, max) = iter.size_hint();
321
322				match max {
323					// If the upper bound is `0` and the stack is empty, then there can be no more
324					// descendants.
325					Some(0) if self.stack.is_empty() => (0, Some(0)),
326
327					// Otherwise, if there could be 1 or more children in the current iterator, then
328					// those children could add extra `ChildrenIter`s to the stack, so we don't know
329					// the upper bound.
330					_ => (min, None),
331				}
332			},
333		}
334	}
335}
336
337impl<'arena, Branch> FusedIterator for Descendants<'arena, Branch>
338where
339	Branch: BranchNode + 'arena,
340	for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
341{
342}
343
344impl<'arena, Linked: Node> Iterator for PrecedingSiblings<'arena, Linked>
345where
346	Linked::Base: LinkedNode,
347{
348	type Item = <Linked::Base as Node>::Token;
349
350	#[inline]
351	fn next(&mut self) -> Option<Self::Item> {
352		self.prev.map(|child| {
353			self.prev = self.arena.0[child.idx()].prev();
354
355			child
356		})
357	}
358
359	#[inline]
360	fn size_hint(&self) -> (usize, Option<usize>) {
361		match &self.prev {
362			None => (0, Some(0)),
363			Some(_) => (1, None),
364		}
365	}
366}
367
368impl<'arena, Linked: Node> FusedIterator for PrecedingSiblings<'arena, Linked> where Linked::Base: LinkedNode {}
369
370impl<'arena, Linked: Node> Iterator for FollowingSiblings<'arena, Linked>
371where
372	Linked::Base: LinkedNode,
373{
374	type Item = <Linked::Base as Node>::Token;
375
376	#[inline]
377	fn next(&mut self) -> Option<Self::Item> {
378		self.next.map(|child| {
379			self.next = self.arena.0[child.idx()].next();
380
381			child
382		})
383	}
384
385	#[inline]
386	fn size_hint(&self) -> (usize, Option<usize>) {
387		match &self.next {
388			None => (0, Some(0)),
389			Some(_) => (1, None),
390		}
391	}
392}
393
394impl<'arena, Linked: Node> FusedIterator for FollowingSiblings<'arena, Linked> where Linked::Base: LinkedNode {}