use std::collections::hash_map::Iter as HMIter;
use std::{hash::Hash, iter::FusedIterator, marker::PhantomData};
use crate::{path::Path, prelude::DiffNode, tree::node::TreeNode};
use super::super::{NodeIDX, Tree};
#[derive(Debug, PartialEq)]
pub enum Traversal<N, B> {
Start(N),
Step {
up: usize,
branch: B,
data: N,
},
}
impl<N, B> Traversal<N, B> {
pub fn take(self) -> N {
match self {
Self::Start(data) => data,
Self::Step {
up: _,
branch: _,
data,
} => data,
}
}
pub fn map<M>(self, op: impl Fn(N) -> M) -> Traversal<M, B> {
match self {
Self::Start(data) => Traversal::Start(op(data)),
Self::Step { up, branch, data } => Traversal::Step {
up,
branch,
data: op(data),
},
}
}
pub fn data(&self) -> &N {
match self {
Self::Start(data) => data,
Self::Step {
up: _,
branch: _,
data,
} => data,
}
}
pub fn branch(&self) -> Option<&B> {
match self {
Self::Start(_) => None,
Self::Step {
up: _,
branch,
data: _,
} => Some(branch),
}
}
pub fn up(&self) -> usize {
match self {
Self::Start(_) => 0,
Self::Step {
up,
branch: _,
data: _,
} => *up,
}
}
pub(crate) fn truncate_up(&mut self, cut: usize) {
if let Self::Step { up, branch, data } = self {
*up -= cut;
}
}
pub fn is_root(&self) -> bool {
match self {
Traversal::Start(_) => true,
Traversal::Step { .. } => false,
}
}
}
pub trait TreeIterTarget<'a, N, B> {
type Target;
fn target(tree: &'a Tree<N, B>, idx: NodeIDX) -> Self::Target;
}
impl<'a, N, B> TreeIterTarget<'a, N, B> for &'a TreeNode<N, B> {
type Target = Self;
fn target(tree: &'a Tree<N, B>, idx: NodeIDX) -> Self::Target {
&tree.nodes[idx]
}
}
impl<'a, N, B> TreeIterTarget<'a, N, B> for &'a N {
type Target = Self;
fn target(tree: &'a Tree<N, B>, idx: NodeIDX) -> Self::Target {
&tree.nodes[idx].value
}
}
impl<'a, N, B> TreeIterTarget<'a, N, B> for () {
type Target = Self;
fn target(_: &'a Tree<N, B>, _: NodeIDX) -> Self::Target {}
}
impl<'a, N, B> TreeIterTarget<'a, N, B> for NodeIDX {
type Target = Self;
fn target(_: &'a Tree<N, B>, idx: NodeIDX) -> Self::Target {
idx
}
}
pub struct Iter<'a, N, B, T>
where
T: TreeIterTarget<'a, N, B>,
{
tree: &'a Tree<N, B>,
root: Option<NodeIDX>,
stages: Vec<HMIter<'a, B, usize>>,
up: usize,
_phantom: PhantomData<T>,
}
impl<'a, N, B, T> Iter<'a, N, B, T>
where
T: TreeIterTarget<'a, N, B>,
{
pub fn new(tree: &'a Tree<N, B>) -> Self {
Self {
tree,
root: tree.get_root_idx(),
stages: vec![],
up: 0,
_phantom: PhantomData,
}
}
pub fn up(&self) -> usize {
self.up
}
}
impl<'a, N, B, T> Iter<'a, N, B, T>
where
B: Clone + Eq + Hash,
T: TreeIterTarget<'a, N, B>,
{
pub fn new_sub_state(tree: &'a Tree<N, B>, path: Path<B>) -> Result<Self, Option<Path<B>>> {
Ok(Self {
tree,
root: Some(
tree.get_idx(&path, None)
.map_err(|r| r.map(|(_, idx_p)| path.path_to(idx_p)))?,
),
stages: vec![],
up: 0,
_phantom: PhantomData,
})
}
pub fn is_last_child(&mut self) -> bool {
if let Some(last) = self.stages.last_mut() {
last.peekable().peek().is_none()
} else {
true
}
}
}
impl<'a, N, B, T> Iterator for Iter<'a, N, B, T>
where
T: TreeIterTarget<'a, N, B>,
{
type Item = Traversal<T::Target, &'a B>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(last) = self.stages.last_mut() {
if let Some((branch, node_idx)) = last.next() {
let node = &self.tree.nodes[*node_idx];
self.stages.push(node.children.iter());
Some(Traversal::Step {
up: std::mem::replace(&mut self.up, 0),
branch,
data: T::target(self.tree, *node_idx),
})
} else {
self.stages.pop();
self.up += 1;
self.next()
}
} else if let Some(root) = self.root.take() {
let node = &self.tree.nodes[root];
self.stages.push(node.children.iter());
Some(Traversal::Start(T::target(self.tree, root)))
} else {
None
}
}
}
impl<'a, N, B, T> FusedIterator for Iter<'a, N, B, T> where T: TreeIterTarget<'a, N, B> {}
impl<'a, N, B> IntoIterator for &'a Tree<N, B> {
type Item = Traversal<&'a N, &'a B>;
type IntoIter = Iter<'a, N, B, &'a N>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter::new(self)
}
}
pub trait TreeIntoIterTarget<N, B> {
type Target;
fn target(node: TreeNode<N, B>) -> Self::Target;
}
impl<N, B> TreeIntoIterTarget<N, B> for N {
type Target = Self;
fn target(node: TreeNode<N, B>) -> Self::Target {
node.value
}
}
impl<N, B> TreeIntoIterTarget<N, B> for TreeNode<N, B> {
type Target = Self;
fn target(node: TreeNode<N, B>) -> Self::Target {
node
}
}
pub struct IntoIter<N, B, T>
where
B: Clone,
T: TreeIntoIterTarget<N, B>,
{
idxs: Vec<Traversal<NodeIDX, B>>,
nodes: Vec<Option<TreeNode<N, B>>>,
_phantom: PhantomData<T>,
}
impl<N, B, T> IntoIter<N, B, T>
where
B: Clone,
T: TreeIntoIterTarget<N, B>,
{
pub fn new(tree: Tree<N, B>) -> Self {
let mut s = Self {
idxs: Iter::<N, B, NodeIDX>::new(&tree)
.map(|n| match n {
Traversal::Start(idx) => Traversal::Start(idx),
Traversal::Step { up, branch, data } => Traversal::Step {
up,
branch: branch.clone(),
data,
},
})
.collect(),
nodes: tree.nodes.into_iter().map(Some).collect(),
_phantom: PhantomData,
};
s.idxs.reverse();
s
}
}
impl<N, B, T> Iterator for IntoIter<N, B, T>
where
B: Clone,
T: TreeIntoIterTarget<N, B>,
{
type Item = Traversal<T::Target, B>;
fn next(&mut self) -> Option<Self::Item> {
match self.idxs.pop() {
Some(Traversal::Start(idx)) => {
Some(Traversal::Start(T::target(self.nodes[idx].take().unwrap())))
}
Some(Traversal::Step { up, branch, data }) => Some(Traversal::Step {
up,
branch,
data: T::target(self.nodes[data].take().unwrap()),
}),
None => None,
}
}
}
impl<N, B> IntoIterator for Tree<N, B>
where
B: Clone,
{
type Item = Traversal<N, B>;
type IntoIter = IntoIter<N, B, N>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter::new(self)
}
}