Add ancestor iteration to XML nodes.

This commit is contained in:
David Wendt 2020-05-16 14:31:11 -04:00
parent a2836a0b92
commit 74912525ed
2 changed files with 47 additions and 0 deletions

View File

@ -141,3 +141,35 @@ impl<'gc> Iterator for WalkIter<'gc> {
}
}
}
/// Iterator that yields indirect descendents of an XML node.
pub struct AnscIter<'gc> {
next: Option<XMLNode<'gc>>,
}
impl<'gc> AnscIter<'gc> {
/// Construct a new `AnscIter` that lists the parents of an XML node.
///
/// This function should be called with the parent of the node being
/// iterated.
pub fn for_node(next: Option<XMLNode<'gc>>) -> Self {
Self { next }
}
}
impl<'gc> Iterator for AnscIter<'gc> {
type Item = XMLNode<'gc>;
fn next(&mut self) -> Option<Self::Item> {
let parent = self.next;
if let Some(parent) = parent {
match parent.parent() {
Ok(gp) => self.next = gp,
_ => self.next = None,
}
}
parent
}
}

View File

@ -814,6 +814,21 @@ impl<'gc> XMLNode<'gc> {
}
}
/// Returns an iterator that yields ancestor nodes.
///
/// Yields None if this node does not have a parent.
pub fn ancestors(self) -> Option<impl Iterator<Item = XMLNode<'gc>>> {
let parent = match *self.0.read() {
XMLNodeData::DocumentRoot { .. } => return None,
XMLNodeData::Element { parent, .. } => parent,
XMLNodeData::Text { parent, .. } => parent,
XMLNodeData::Comment { parent, .. } => parent,
XMLNodeData::DocType { parent, .. } => parent,
};
Some(xml::iterators::AnscIter::for_node(parent))
}
/// Get the already-instantiated script object from the current node.
fn get_script_object(self) -> Option<Object<'gc>> {
match &*self.0.read() {