use std::{collections::VecDeque, iter::FusedIterator};
use crate::{sealed::Idx, Arena, BaseNode, BranchNode, LinkedNode, Node};
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Ancestors<'arena, Base: BaseNode> {
arena: &'arena Arena<Base>,
parent: Option<<<Base as BaseNode>::Branch as Node>::Token>,
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ChildrenLinked<'arena, Branch: BranchNode>
where
Branch::Base: LinkedNode,
{
arena: &'arena Arena<Branch::Base>,
child_front: Option<<Branch::Base as Node>::Token>,
child_back: Option<<Branch::Base as Node>::Token>,
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Descendants<'arena, Branch: BranchNode + 'arena>
where
for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
{
arena: &'arena Arena<Branch::Base>,
current: Option<Branch::ChildrenIter<'arena>>,
stack: VecDeque<Branch::ChildrenIter<'arena>>,
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct PrecedingSiblings<'arena, Linked: Node>
where
Linked::Base: LinkedNode,
{
arena: &'arena Arena<Linked::Base>,
prev: Option<<Linked::Base as Node>::Token>,
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct FollowingSiblings<'arena, Linked: Node>
where
Linked::Base: LinkedNode,
{
arena: &'arena Arena<Linked::Base>,
next: Option<<Linked::Base as Node>::Token>,
}
impl<'arena, Base: BaseNode> Ancestors<'arena, Base> {
#[inline(always)]
pub(super) const fn new(
arena: &'arena Arena<Base>,
parent: Option<<<Base as BaseNode>::Branch as Node>::Token>,
) -> Self {
Self { arena, parent }
}
}
impl<'arena, Base: BaseNode> Iterator for Ancestors<'arena, Base> {
type Item = <<Base as BaseNode>::Branch as Node>::Token;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.parent.map(|parent| {
self.parent = self.arena.0[parent.idx()].parent();
parent
})
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.parent {
None => (0, Some(0)),
Some(_) => (1, None),
}
}
}
impl<'arena, Base: BaseNode> FusedIterator for Ancestors<'arena, Base> {}
impl<'arena, Branch> ChildrenLinked<'arena, Branch>
where
Branch: BranchNode,
Branch::Base: LinkedNode,
{
#[inline(always)]
pub(super) const fn new(
arena: &'arena Arena<Branch::Base>,
child_front: Option<<Branch::Base as Node>::Token>,
child_back: Option<<Branch::Base as Node>::Token>,
) -> Self {
Self {
arena,
child_front,
child_back,
}
}
}
impl<'arena, Branch> Descendants<'arena, Branch>
where
Branch: BranchNode + 'arena,
for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
{
#[inline(always)]
pub(super) fn new(branch: &'arena Branch, arena: &'arena Arena<Branch::Base>) -> Self {
Self {
arena,
current: Some(branch.children(arena)),
stack: VecDeque::new(),
}
}
}
impl<'arena, Linked: Node> PrecedingSiblings<'arena, Linked>
where
Linked::Base: LinkedNode,
{
#[inline(always)]
pub(super) const fn new(arena: &'arena Arena<Linked::Base>, prev: Option<<Linked::Base as Node>::Token>) -> Self {
Self { arena, prev }
}
}
impl<'arena, Linked: Node> FollowingSiblings<'arena, Linked>
where
Linked::Base: LinkedNode,
{
#[inline(always)]
pub(super) const fn new(arena: &'arena Arena<Linked::Base>, next: Option<<Linked::Base as Node>::Token>) -> Self {
Self { arena, next }
}
}
impl<'arena, Branch> Iterator for ChildrenLinked<'arena, Branch>
where
Branch: BranchNode,
Branch::Base: LinkedNode,
{
type Item = <Branch::Base as Node>::Token;
fn next(&mut self) -> Option<Self::Item> {
self.child_front.map(|child| {
match self.child_back {
Some(back) if child == back => {
(self.child_front, self.child_back) = (None, None);
},
_ => self.child_front = self.arena.0[child.idx()].next(),
}
child
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
match (&self.child_front, &self.child_back) {
(None, None) => (0, Some(0)),
(Some(front), Some(back)) if front == back => (1, Some(1)),
(Some(_), Some(_)) => (2, None),
(..) => (0, None),
}
}
}
impl<'arena, Branch> DoubleEndedIterator for ChildrenLinked<'arena, Branch>
where
Branch: BranchNode,
Branch::Base: LinkedNode,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.child_back.map(|child| {
match self.child_front {
Some(front) if child == front => {
(self.child_front, self.child_back) = (None, None);
},
_ => self.child_back = self.arena.0[child.idx()].prev(),
}
child
})
}
}
impl<'arena, Branch> FusedIterator for ChildrenLinked<'arena, Branch>
where
Branch: BranchNode,
Branch::Base: LinkedNode,
{
}
impl<'arena, Branch> Iterator for Descendants<'arena, Branch>
where
Branch: BranchNode + 'arena,
for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
{
type Item = <Branch::Base as Node>::Token;
fn next(&mut self) -> Option<Self::Item> {
let token = match &mut self.current {
None => None,
Some(iter) => match iter.next() {
Some(token) => Some(token),
None => {
self.current = None;
let mut token = None;
while let Some(mut iter) = self.stack.pop_front() {
match iter.next() {
Some(child) => {
self.current = Some(iter);
token = Some(child);
break;
},
None => continue,
}
}
token
},
},
};
if let Some(branch) = token
.as_ref()
.and_then(|token| <&Branch as TryFrom<&Branch::Base>>::try_from(&self.arena.0[token.idx()]).ok())
{
self.stack.push_back(branch.children(self.arena));
}
token
}
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.current {
None => (0, Some(0)),
Some(iter) => {
let (min, max) = iter.size_hint();
match max {
Some(0) if self.stack.is_empty() => (0, Some(0)),
_ => (min, None),
}
},
}
}
}
impl<'arena, Branch> FusedIterator for Descendants<'arena, Branch>
where
Branch: BranchNode + 'arena,
for<'base> &'base Branch: TryFrom<&'base Branch::Base>,
{
}
impl<'arena, Linked: Node> Iterator for PrecedingSiblings<'arena, Linked>
where
Linked::Base: LinkedNode,
{
type Item = <Linked::Base as Node>::Token;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.prev.map(|child| {
self.prev = self.arena.0[child.idx()].prev();
child
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.prev {
None => (0, Some(0)),
Some(_) => (1, None),
}
}
}
impl<'arena, Linked: Node> FusedIterator for PrecedingSiblings<'arena, Linked> where Linked::Base: LinkedNode {}
impl<'arena, Linked: Node> Iterator for FollowingSiblings<'arena, Linked>
where
Linked::Base: LinkedNode,
{
type Item = <Linked::Base as Node>::Token;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.next.map(|child| {
self.next = self.arena.0[child.idx()].next();
child
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.next {
None => (0, Some(0)),
Some(_) => (1, None),
}
}
}
impl<'arena, Linked: Node> FusedIterator for FollowingSiblings<'arena, Linked> where Linked::Base: LinkedNode {}