use crate::node::Node;
impl Node {
pub fn walk(&self, f: &mut impl FnMut(&Node)) {
f(self);
if let Some(children) = &self.content {
for child in children {
child.walk(f);
}
}
}
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Node)) {
f(self);
if let Some(children) = &mut self.content {
for child in children {
child.walk_mut(f);
}
}
}
pub fn find(&self, mut pred: impl FnMut(&Node) -> bool) -> Option<&Node> {
self.descendants().find(|n| pred(n))
}
pub fn find_mut(&mut self, mut pred: impl FnMut(&Node) -> bool) -> Option<&mut Node> {
if pred(self) {
return Some(self);
}
let children = self.content.as_mut()?;
for child in children {
if let Some(found) = child.find_mut(&mut pred) {
return Some(found);
}
}
None
}
pub fn find_all(&self, mut pred: impl FnMut(&Node) -> bool) -> Vec<&Node> {
self.descendants().filter(|n| pred(n)).collect()
}
pub fn find_all_mut(&mut self, pred: &mut impl FnMut(&Node) -> bool) -> Vec<&mut Node> {
let mut out = Vec::new();
self.collect_mut(pred, &mut out);
out
}
fn collect_mut<'a>(
&'a mut self,
pred: &mut impl FnMut(&Node) -> bool,
out: &mut Vec<&'a mut Node>,
) {
let matched = pred(self);
let children_ptr = self.content.as_mut().map(|c| c as *mut Vec<Node>);
if matched {
out.push(self);
}
if let Some(ptr) = children_ptr {
let children = unsafe { &mut *ptr };
for child in children {
child.collect_mut(pred, out);
}
}
}
#[inline]
pub fn descendants(&self) -> Descendants<'_> {
Descendants { stack: vec![self] }
}
}
pub struct Descendants<'a> {
stack: Vec<&'a Node>,
}
impl<'a> Iterator for Descendants<'a> {
type Item = &'a Node;
fn next(&mut self) -> Option<&'a Node> {
let node = self.stack.pop()?;
if let Some(children) = &node.content {
self.stack.extend(children.iter().rev());
}
Some(node)
}
}