use std::iter::FusedIterator;
use crate::arena::NodeId;
use crate::document::Document;
use crate::node::{Attribute, NodeKind};
use crate::refs::{ElementRef, NodeRef};
#[derive(Debug, Clone)]
pub struct Children<'a> {
doc: &'a Document,
front: Option<NodeId>,
back: Option<NodeId>,
}
impl<'a> Children<'a> {
pub(crate) fn new(doc: &'a Document, parent: NodeId) -> Self {
Self {
doc,
front: doc.first_child(parent),
back: doc.last_child(parent),
}
}
}
impl<'a> Iterator for Children<'a> {
type Item = NodeRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
let id = self.front?;
if self.front == self.back {
self.front = None;
self.back = None;
} else {
self.front = self.doc.next_sibling(id);
}
Some(NodeRef::new(self.doc, id))
}
}
impl DoubleEndedIterator for Children<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
let id = self.back?;
if self.front == self.back {
self.front = None;
self.back = None;
} else {
self.back = self.doc.prev_sibling(id);
}
Some(NodeRef::new(self.doc, id))
}
}
impl FusedIterator for Children<'_> {}
#[derive(Debug, Clone)]
pub struct ChildElements<'a> {
doc: &'a Document,
current: Option<NodeId>,
name_filter: Option<String>,
}
impl<'a> ChildElements<'a> {
pub(crate) fn new(doc: &'a Document, parent: NodeId, name: Option<&str>) -> Self {
Self {
doc,
current: doc.first_child(parent),
name_filter: name.map(String::from),
}
}
}
impl<'a> Iterator for ChildElements<'a> {
type Item = ElementRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(id) = self.current {
self.current = self.doc.next_sibling(id);
if let Some(data) = self.doc.arena.get(id) {
if let NodeKind::Element(ref el_data) = data.kind {
if self.name_filter.as_ref().is_none_or(|n| n == &el_data.name) {
return Some(ElementRef::new(self.doc, id));
}
}
}
}
None
}
}
impl FusedIterator for ChildElements<'_> {}
#[derive(Debug, Clone)]
pub struct Siblings<'a> {
doc: &'a Document,
current: Option<NodeId>,
}
impl<'a> Siblings<'a> {
pub(crate) fn new(doc: &'a Document, node: NodeId) -> Self {
Self {
doc,
current: doc.next_sibling(node),
}
}
}
impl<'a> Iterator for Siblings<'a> {
type Item = NodeRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
let id = self.current?;
self.current = self.doc.next_sibling(id);
Some(NodeRef::new(self.doc, id))
}
}
impl FusedIterator for Siblings<'_> {}
#[derive(Debug, Clone)]
pub struct Attributes<'a> {
inner: std::slice::Iter<'a, Attribute>,
}
impl<'a> Attributes<'a> {
pub(crate) fn new(attrs: &'a [Attribute]) -> Self {
Self {
inner: attrs.iter(),
}
}
pub(crate) fn empty() -> Self {
Self { inner: [].iter() }
}
}
impl<'a> Iterator for Attributes<'a> {
type Item = (&'a str, &'a str);
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|attr| (attr.name.as_str(), attr.value.as_str()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl DoubleEndedIterator for Attributes<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|attr| (attr.name.as_str(), attr.value.as_str()))
}
}
impl ExactSizeIterator for Attributes<'_> {}
impl FusedIterator for Attributes<'_> {}
#[derive(Debug, Clone)]
pub struct Descendants<'a> {
doc: &'a Document,
root: NodeId,
current: Option<NodeId>,
}
impl<'a> Descendants<'a> {
pub(crate) fn new(doc: &'a Document, root: NodeId) -> Self {
Self {
doc,
root,
current: doc.first_child(root),
}
}
fn advance(&self, node: NodeId) -> Option<NodeId> {
if let Some(child) = self.doc.first_child(node) {
return Some(child);
}
let mut current = node;
loop {
if current == self.root {
return None;
}
if let Some(sibling) = self.doc.next_sibling(current) {
return Some(sibling);
}
current = self.doc.parent(current)?;
}
}
}
impl<'a> Iterator for Descendants<'a> {
type Item = NodeRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
let id = self.current?;
self.current = self.advance(id);
Some(NodeRef::new(self.doc, id))
}
}
impl FusedIterator for Descendants<'_> {}