use super::node::Node;
pub struct NodeChildIterator<'a> {
node: &'a Node,
index: usize,
mapping_phase: usize, }
impl<'a> NodeChildIterator<'a> {
pub fn new(node: &'a Node) -> Self {
Self {
node,
index: 0,
mapping_phase: 0,
}
}
}
impl<'a> Iterator for NodeChildIterator<'a> {
type Item = &'a Node;
fn next(&mut self) -> Option<Self::Item> {
match self.node {
Node::Array(items)
| Node::Set(items)
| Node::Document(items)
| Node::Documents(items) => {
if self.index < items.len() {
let item = &items[self.index];
self.index += 1;
Some(item)
} else {
None
}
}
Node::Mapping(pairs) => {
if self.mapping_phase == 0 {
if let Some((key, _)) = pairs.get(self.index) {
self.index += 1;
return Some(key);
} else {
self.mapping_phase = 1;
self.index = 0;
}
}
if self.mapping_phase == 1 {
if let Some((_, value)) = pairs.get(self.index) {
self.index += 1;
return Some(value);
} else {
self.mapping_phase = 2;
}
}
None
}
Node::Anchored(inner, _) | Node::Tagged(inner, _) => {
if self.index == 0 {
self.index = 1;
Some(inner.as_ref())
} else {
None
}
}
_ => None,
}
}
}
impl Node {
pub fn children(&self) -> NodeChildIterator {
NodeChildIterator::new(self)
}
pub fn visit<F>(&self, mut visitor: F)
where
F: FnMut(&Node, usize) -> bool,
{
self.visit_internal(&mut visitor, 0);
}
fn visit_internal<F>(&self, visitor: &mut F, depth: usize) -> bool
where
F: FnMut(&Node, usize) -> bool,
{
if !visitor(self, depth) {
return false;
}
match self {
Node::Array(items)
| Node::Set(items)
| Node::Document(items)
| Node::Documents(items) => {
for item in items {
if !item.visit_internal(visitor, depth + 1) {
return false;
}
}
}
Node::Mapping(pairs) => {
for (key, value) in pairs {
if !key.visit_internal(visitor, depth + 1) {
return false;
}
if !value.visit_internal(visitor, depth + 1) {
return false;
}
}
}
Node::Anchored(inner, _) | Node::Tagged(inner, _) => {
return inner.visit_internal(visitor, depth + 1);
}
_ => {}
}
true
}
pub fn visit_mut<F>(&mut self, mut visitor: F)
where
F: FnMut(&mut Node, usize) -> bool,
{
self.visit_mut_internal(&mut visitor, 0);
}
fn visit_mut_internal<F>(&mut self, visitor: &mut F, depth: usize) -> bool
where
F: FnMut(&mut Node, usize) -> bool,
{
if !visitor(self, depth) {
return false;
}
match self {
Node::Array(items)
| Node::Set(items)
| Node::Document(items)
| Node::Documents(items) => {
for item in items {
if !item.visit_mut_internal(visitor, depth + 1) {
return false;
}
}
}
Node::Mapping(pairs) => {
for (key, value) in pairs {
if !key.visit_mut_internal(visitor, depth + 1) {
return false;
}
if !value.visit_mut_internal(visitor, depth + 1) {
return false;
}
}
}
Node::Anchored(inner, _) | Node::Tagged(inner, _) => {
return inner.visit_mut_internal(visitor, depth + 1);
}
_ => {}
}
true
}
pub fn count_nodes(&self) -> usize {
let mut count = 0;
self.visit(|_, _| {
count += 1;
true
});
count
}
pub fn max_depth(&self) -> usize {
let mut max = 0;
self.visit(|_, depth| {
if depth > max {
max = depth;
}
true
});
max
}
pub fn find_all<F>(&self, mut predicate: F) -> alloc::vec::Vec<&Node>
where
F: FnMut(&Node) -> bool,
{
let mut results = alloc::vec::Vec::new();
self.find_all_internal(&mut predicate, &mut results);
results
}
fn find_all_internal<'a, F>(
&'a self,
predicate: &mut F,
results: &mut alloc::vec::Vec<&'a Node>,
) where
F: FnMut(&Node) -> bool,
{
if predicate(self) {
results.push(self);
}
match self {
Node::Array(items)
| Node::Set(items)
| Node::Document(items)
| Node::Documents(items) => {
for item in items {
item.find_all_internal(predicate, results);
}
}
Node::Mapping(pairs) => {
for (key, value) in pairs {
key.find_all_internal(predicate, results);
value.find_all_internal(predicate, results);
}
}
Node::Anchored(inner, _) | Node::Tagged(inner, _) => {
inner.find_all_internal(predicate, results);
}
_ => {}
}
}
pub fn find_first<F>(&self, mut predicate: F) -> Option<&Node>
where
F: FnMut(&Node) -> bool,
{
self.find_first_internal(&mut predicate)
}
fn find_first_internal<F>(&self, predicate: &mut F) -> Option<&Node>
where
F: FnMut(&Node) -> bool,
{
if predicate(self) {
return Some(self);
}
match self {
Node::Array(items)
| Node::Set(items)
| Node::Document(items)
| Node::Documents(items) => {
for item in items {
if let Some(found) = item.find_first_internal(predicate) {
return Some(found);
}
}
}
Node::Mapping(pairs) => {
for (key, value) in pairs {
if let Some(found) = key.find_first_internal(predicate) {
return Some(found);
}
if let Some(found) = value.find_first_internal(predicate) {
return Some(found);
}
}
}
Node::Anchored(inner, _) | Node::Tagged(inner, _) => {
return inner.find_first_internal(predicate);
}
_ => {}
}
None
}
}