use std::{
collections::VecDeque,
marker::PhantomData,
ops::{Deref, DerefMut},
};
use crate::traversal_order::{BreadthFirst, DepthFirst, TraversalOrder};
pub trait TreeNodeMut {
fn children_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Self>;
fn iter_mut<T: TraversalOrder>(&mut self) -> TreeIterMut<'_, Self, T>
where
Self: Sized,
{
TreeIterMut::new([self])
}
}
#[derive(Debug)]
pub struct TreeIterMut<'a, N, T> {
nodes: VecDeque<&'a mut N>,
_order: PhantomData<T>,
}
impl<'a, N, T> TreeIterMut<'a, N, T> {
pub fn new(roots: impl IntoIterator<Item = &'a mut N>) -> Self {
Self {
nodes: roots.into_iter().collect(),
_order: PhantomData,
}
}
}
#[derive(Debug)]
pub struct BFSRefMutGuard<'a: 'b, 'b, N: TreeNodeMut> {
iter: &'b mut TreeIterMut<'a, N, BreadthFirst>,
node: Option<&'a mut N>,
}
impl<N: TreeNodeMut> Drop for BFSRefMutGuard<'_, '_, N> {
fn drop(&mut self) {
let node = self.node.take().unwrap();
self.iter.nodes.extend(node.children_mut());
}
}
impl<N: TreeNodeMut> Deref for BFSRefMutGuard<'_, '_, N> {
type Target = N;
fn deref(&self) -> &Self::Target {
self.node.as_ref().unwrap()
}
}
impl<N: TreeNodeMut> DerefMut for BFSRefMutGuard<'_, '_, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.node.as_mut().unwrap()
}
}
impl<'a, N: TreeNodeMut> TreeIterMut<'a, N, BreadthFirst> {
pub fn next(&mut self) -> Option<BFSRefMutGuard<'a, '_, N>> {
self.nodes.pop_front().map(|node| BFSRefMutGuard {
iter: self,
node: Some(node),
})
}
}
#[derive(Debug)]
pub struct DFSRefMutGuard<'a: 'b, 'b, N: TreeNodeMut> {
iter: &'b mut TreeIterMut<'a, N, DepthFirst>,
node: Option<&'a mut N>,
}
impl<N: TreeNodeMut> Drop for DFSRefMutGuard<'_, '_, N> {
fn drop(&mut self) {
let node = self.node.take().unwrap();
for child in node.children_mut().rev() {
self.iter.nodes.push_front(child);
}
}
}
impl<N: TreeNodeMut> Deref for DFSRefMutGuard<'_, '_, N> {
type Target = N;
fn deref(&self) -> &Self::Target {
self.node.as_ref().unwrap()
}
}
impl<N: TreeNodeMut> DerefMut for DFSRefMutGuard<'_, '_, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.node.as_mut().unwrap()
}
}
impl<'a, N: TreeNodeMut> TreeIterMut<'a, N, DepthFirst> {
pub fn next(&mut self) -> Option<DFSRefMutGuard<'a, '_, N>> {
self.nodes.pop_front().map(|node| DFSRefMutGuard {
iter: self,
node: Some(node),
})
}
}