diff --git a/core/src/xml/iterators.rs b/core/src/xml/iterators.rs index e5f1cb782..e1394dc95 100644 --- a/core/src/xml/iterators.rs +++ b/core/src/xml/iterators.rs @@ -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>, +} + +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>) -> Self { + Self { next } + } +} + +impl<'gc> Iterator for AnscIter<'gc> { + type Item = XMLNode<'gc>; + + fn next(&mut self) -> Option { + let parent = self.next; + + if let Some(parent) = parent { + match parent.parent() { + Ok(gp) => self.next = gp, + _ => self.next = None, + } + } + + parent + } +} diff --git a/core/src/xml/tree.rs b/core/src/xml/tree.rs index ef9350e2c..254264623 100644 --- a/core/src/xml/tree.rs +++ b/core/src/xml/tree.rs @@ -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>> { + 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> { match &*self.0.read() {