virtual_dom/
dom_node.rs

1use std::cell::{Ref, RefCell, RefMut};
2use std::collections::HashMap;
3use std::fmt;
4use std::rc::{Rc, Weak};
5
6use crate::{is_void_element, Html, IterableNodes};
7
8/// Strong link
9type Link = Rc<RefCell<DomNodeData>>;
10
11type WeakLink = Weak<RefCell<DomNodeData>>;
12
13/// Based on https://docs.rs/rctree/latest/rctree/struct.Node.html
14pub struct DomNode(Link);
15
16pub struct WeakDomNode(WeakLink);
17
18#[derive(Debug, Clone, PartialEq)]
19pub enum DomNodeKind {
20    Text {
21        text: String,
22    },
23    Element {
24        tag: String,
25        attributes: HashMap<String, String>,
26    },
27}
28
29struct DomNodeData {
30    kind: DomNodeKind,
31    parent: Option<WeakLink>,
32    first_child: Option<Link>,
33    last_child: Option<WeakLink>,
34    previous_sibling: Option<WeakLink>,
35    next_sibling: Option<Link>,
36}
37
38/// Cloning a `Node` only increments a reference count. It does not copy the data.
39impl Clone for DomNode {
40    fn clone(&self) -> Self {
41        DomNode(Rc::clone(&self.0))
42    }
43}
44
45impl PartialEq for DomNode {
46    fn eq(&self, other: &DomNode) -> bool {
47        Rc::ptr_eq(&self.0, &other.0)
48    }
49}
50
51impl fmt::Debug for DomNode {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        fmt::Debug::fmt(&self.kind(), f)
54    }
55}
56
57impl DomNode {
58    /// Creates a new node
59    pub fn new(kind: DomNodeKind) -> DomNode {
60        DomNode(Rc::new(RefCell::new(DomNodeData {
61            kind,
62            parent: None,
63            first_child: None,
64            last_child: None,
65            previous_sibling: None,
66            next_sibling: None,
67        })))
68    }
69
70    pub fn create_element(tag: impl Into<String>) -> DomNode {
71        Self::new(DomNodeKind::Element {
72            tag: tag.into(),
73            attributes: HashMap::new(),
74        })
75    }
76
77    pub fn create_element_with_attributes(
78        tag: impl Into<String>,
79        attributes: HashMap<String, String>,
80    ) -> DomNode {
81        Self::new(DomNodeKind::Element {
82            tag: tag.into(),
83            attributes,
84        })
85    }
86
87    pub fn create_text(text: impl Into<String>) -> DomNode {
88        Self::new(DomNodeKind::Text { text: text.into() })
89    }
90
91    pub fn get_attribute(&self, attribute: &str) -> Option<String> {
92        match &*self.kind() {
93            DomNodeKind::Text { .. } => None,
94            DomNodeKind::Element { attributes, .. } => attributes.get(attribute).cloned(),
95        }
96    }
97
98    pub fn set_attribute(&mut self, key: &str, value: &str) {
99        if let DomNodeKind::Element { attributes, .. } = &mut *self.kind_mut() {
100            attributes.insert(key.into(), value.into());
101        }
102    }
103
104    /// Returns a weak referece to a node.
105    pub fn downgrade(&self) -> WeakDomNode {
106        WeakDomNode(Rc::downgrade(&self.0))
107    }
108
109    /// Returns a parent node, unless this node is the root of the tree.
110    ///
111    /// # Panics
112    ///
113    /// Panics if the node is currently mutably borrowed.
114    pub fn parent(&self) -> Option<DomNode> {
115        Some(DomNode(self.0.borrow().parent.as_ref()?.upgrade()?))
116    }
117
118    /// Returns a first child of this node, unless it has no child.
119    ///
120    /// # Panics
121    ///
122    /// Panics if the node is currently mutably borrowed.
123    pub fn first_child(&self) -> Option<DomNode> {
124        Some(DomNode(self.0.borrow().first_child.as_ref()?.clone()))
125    }
126
127    /// Returns a last child of this node, unless it has no child.
128    ///
129    /// # Panics
130    ///
131    /// Panics if the node is currently mutably borrowed.
132    pub fn last_child(&self) -> Option<DomNode> {
133        Some(DomNode(self.0.borrow().last_child.as_ref()?.upgrade()?))
134    }
135
136    /// Returns the previous sibling of this node, unless it is a first child.
137    ///
138    /// # Panics
139    ///
140    /// Panics if the node is currently mutably borrowed.
141    pub fn previous_sibling(&self) -> Option<DomNode> {
142        Some(DomNode(
143            self.0.borrow().previous_sibling.as_ref()?.upgrade()?,
144        ))
145    }
146
147    /// Returns the next sibling of this node, unless it is a last child.
148    ///
149    /// # Panics
150    ///
151    /// Panics if the node is currently mutably borrowed.
152    pub fn next_sibling(&self) -> Option<DomNode> {
153        Some(DomNode(self.0.borrow().next_sibling.as_ref()?.clone()))
154    }
155
156    pub fn kind(&self) -> Ref<'_, DomNodeKind> {
157        Ref::map(self.0.borrow(), |v| &v.kind)
158    }
159
160    pub fn kind_mut(&self) -> RefMut<'_, DomNodeKind> {
161        RefMut::map(self.0.borrow_mut(), |v| &mut v.kind)
162    }
163
164    /// Returns an iterator of nodes to this node and its ancestors.
165    ///
166    /// Includes the current node.
167    pub fn ancestors(&self) -> Ancestors {
168        Ancestors(Some(self.clone()))
169    }
170
171    /// Returns an iterator of nodes to this node and the siblings before it.
172    ///
173    /// Includes the current node.
174    pub fn preceding_siblings(&self) -> PrecedingSiblings {
175        PrecedingSiblings(Some(self.clone()))
176    }
177
178    /// Returns an iterator of nodes to this node and the siblings after it.
179    ///
180    /// Includes the current node.
181    pub fn following_siblings(&self) -> FollowingSiblings {
182        FollowingSiblings(Some(self.clone()))
183    }
184
185    /// Returns an iterator of nodes to this node's children.
186    ///
187    /// # Panics
188    ///
189    /// Panics if the node is currently mutably borrowed.
190    pub fn children(&self) -> Children {
191        Children {
192            next: self.first_child(),
193            next_back: self.last_child(),
194        }
195    }
196
197    /// Returns `true` if this node has children nodes.
198    ///
199    /// # Panics
200    ///
201    /// Panics if the node is currently mutably borrowed.
202    pub fn has_children(&self) -> bool {
203        self.first_child().is_some()
204    }
205
206    /// Returns an iterator of nodes to this node and its descendants, in tree order.
207    ///
208    /// Includes the current node.
209    pub fn descendants(&self) -> Descendants {
210        Descendants(self.traverse())
211    }
212
213    /// Returns an iterator of nodes to this node and its descendants, in tree order.
214    pub fn traverse(&self) -> Traverse {
215        Traverse {
216            root: self.clone(),
217            next: Some(NodeEdge::Start(self.clone())),
218            next_back: Some(NodeEdge::End(self.clone())),
219        }
220    }
221
222    /// Remove empty tags or invalid html in a way that makes sense
223    pub fn sanitize_children(&mut self) {
224        for mut c in self.children() {
225            c.sanitize_children();
226        }
227
228        // can't remove while borrowing in c.kind() so getting remove flag instead
229        let should_remove = match &*self.kind() {
230            DomNodeKind::Text { text } if text.is_empty() => true,
231            // remove paragraph if no children
232            DomNodeKind::Element { tag, .. } if tag == "p" && self.first_child().is_none() => true,
233            // remove paragraph if text children are only whitespace
234            DomNodeKind::Element { tag, .. } if tag == "p" => self.children().all(|c| {
235                if let DomNodeKind::Text { text } = &*c.kind() {
236                    text.chars().all(|c| c == ' ')
237                } else {
238                    false
239                }
240            }),
241            _ => false,
242        };
243        if should_remove {
244            self.detach();
245            return;
246        }
247
248        match &mut *self.kind_mut() {
249            // only single whitespace as text
250            DomNodeKind::Text { text } if text.chars().all(|c| c == ' ') => *text = " ".into(),
251            _ => {}
252        };
253    }
254
255    pub fn get_elements_by_tag_name(&self, tag: &str) -> Vec<DomNode> {
256        self.descendants()
257            .filter(|d| {
258                if let DomNodeKind::Element { tag: t, .. } = &*d.kind() {
259                    if t == tag {
260                        return true;
261                    }
262                }
263                false
264            })
265            .collect()
266    }
267
268    pub fn get_element_by_id(&self, id: &str) -> Option<DomNode> {
269        self.descendants().find(|d| {
270            if let DomNodeKind::Element { attributes, .. } = &*d.kind() {
271                if let Some(element_id) = attributes.get("id") {
272                    return element_id == id;
273                }
274            }
275            false
276        })
277    }
278
279    /// Returns the text content of this node and all its descendants.
280    pub fn inner_text(&self) -> String {
281        let mut text = String::new();
282        for descendant in self.descendants() {
283            if let DomNodeKind::Text { text: t } = &*descendant.kind() {
284                text.push_str(t);
285            }
286        }
287        text
288    }
289
290    /// Detaches a node from its parent and siblings. Children are not affected.
291    ///
292    /// # Panics
293    ///
294    /// Panics if the node or one of its adjoining nodes is currently borrowed.
295    pub fn detach(&self) {
296        self.0.borrow_mut().detach();
297    }
298
299    /// Appends a new child to this node, after existing children.
300    ///
301    /// # Panics
302    ///
303    /// Panics if the node, the new child, or one of their adjoining nodes is currently borrowed.
304    pub fn append_child(&self, new_child: impl Into<IterableNodes>) {
305        let iter: IterableNodes = new_child.into();
306        for c in iter.0 {
307            assert!(*self != c, "a node cannot be appended to itself");
308
309            let mut self_borrow = self.0.borrow_mut();
310            let mut last_child_opt = None;
311            {
312                let mut new_child_borrow = c.0.borrow_mut();
313                new_child_borrow.detach();
314                new_child_borrow.parent = Some(Rc::downgrade(&self.0));
315                if let Some(last_child_weak) = self_borrow.last_child.take() {
316                    if let Some(last_child_strong) = last_child_weak.upgrade() {
317                        new_child_borrow.previous_sibling = Some(last_child_weak);
318                        last_child_opt = Some(last_child_strong);
319                    }
320                }
321                self_borrow.last_child = Some(Rc::downgrade(&c.0));
322            }
323
324            if let Some(last_child_strong) = last_child_opt {
325                let mut last_child_borrow = last_child_strong.borrow_mut();
326                debug_assert!(last_child_borrow.next_sibling.is_none());
327                last_child_borrow.next_sibling = Some(c.0);
328            } else {
329                // No last child
330                debug_assert!(self_borrow.first_child.is_none());
331                self_borrow.first_child = Some(c.0);
332            }
333        }
334    }
335
336    /// Prepends a new child to this node, before existing children.
337    ///
338    /// # Panics
339    ///
340    /// Panics if the node, the new child, or one of their adjoining nodes is currently borrowed.
341    pub fn prepend(&self, new_child: DomNode) {
342        assert!(*self != new_child, "a node cannot be prepended to itself");
343
344        let mut self_borrow = self.0.borrow_mut();
345        {
346            let mut new_child_borrow = new_child.0.borrow_mut();
347            new_child_borrow.detach();
348            new_child_borrow.parent = Some(Rc::downgrade(&self.0));
349            match self_borrow.first_child.take() {
350                Some(first_child_strong) => {
351                    {
352                        let mut first_child_borrow = first_child_strong.borrow_mut();
353                        debug_assert!(first_child_borrow.previous_sibling.is_none());
354                        first_child_borrow.previous_sibling = Some(Rc::downgrade(&new_child.0));
355                    }
356                    new_child_borrow.next_sibling = Some(first_child_strong);
357                }
358                None => {
359                    debug_assert!(self_borrow.first_child.is_none());
360                    self_borrow.last_child = Some(Rc::downgrade(&new_child.0));
361                }
362            }
363        }
364        self_borrow.first_child = Some(new_child.0);
365    }
366
367    /// Inserts a new sibling after this node.
368    ///
369    /// # Panics
370    ///
371    /// Panics if the node, the new sibling, or one of their adjoining nodes is currently borrowed.
372    pub fn insert_after(&self, new_sibling: DomNode) {
373        assert!(
374            *self != new_sibling,
375            "a node cannot be inserted after itself"
376        );
377
378        let mut self_borrow = self.0.borrow_mut();
379        {
380            let mut new_sibling_borrow = new_sibling.0.borrow_mut();
381            new_sibling_borrow.detach();
382            new_sibling_borrow.parent = self_borrow.parent.clone();
383            new_sibling_borrow.previous_sibling = Some(Rc::downgrade(&self.0));
384            match self_borrow.next_sibling.take() {
385                Some(next_sibling_strong) => {
386                    {
387                        let mut next_sibling_borrow = next_sibling_strong.borrow_mut();
388                        debug_assert!({
389                            let weak = next_sibling_borrow.previous_sibling.as_ref().unwrap();
390                            Rc::ptr_eq(&weak.upgrade().unwrap(), &self.0)
391                        });
392                        next_sibling_borrow.previous_sibling = Some(Rc::downgrade(&new_sibling.0));
393                    }
394                    new_sibling_borrow.next_sibling = Some(next_sibling_strong);
395                }
396                None => {
397                    if let Some(parent_ref) = self_borrow.parent.as_ref() {
398                        if let Some(parent_strong) = parent_ref.upgrade() {
399                            let mut parent_borrow = parent_strong.borrow_mut();
400                            parent_borrow.last_child = Some(Rc::downgrade(&new_sibling.0));
401                        }
402                    }
403                }
404            }
405        }
406        self_borrow.next_sibling = Some(new_sibling.0);
407    }
408
409    /// Inserts a new sibling before this node.
410    ///
411    /// # Panics
412    ///
413    /// Panics if the node, the new sibling, or one of their adjoining nodes is currently borrowed.
414    pub fn insert_before(&self, new_sibling: DomNode) {
415        assert!(
416            *self != new_sibling,
417            "a node cannot be inserted before itself"
418        );
419
420        let mut self_borrow = self.0.borrow_mut();
421        let mut previous_sibling_opt = None;
422        {
423            let mut new_sibling_borrow = new_sibling.0.borrow_mut();
424            new_sibling_borrow.detach();
425            new_sibling_borrow.parent = self_borrow.parent.clone();
426            new_sibling_borrow.next_sibling = Some(self.0.clone());
427            if let Some(previous_sibling_weak) = self_borrow.previous_sibling.take() {
428                if let Some(previous_sibling_strong) = previous_sibling_weak.upgrade() {
429                    new_sibling_borrow.previous_sibling = Some(previous_sibling_weak);
430                    previous_sibling_opt = Some(previous_sibling_strong);
431                }
432            }
433            self_borrow.previous_sibling = Some(Rc::downgrade(&new_sibling.0));
434        }
435
436        if let Some(previous_sibling_strong) = previous_sibling_opt {
437            let mut previous_sibling_borrow = previous_sibling_strong.borrow_mut();
438            debug_assert!({
439                let rc = previous_sibling_borrow.next_sibling.as_ref().unwrap();
440                Rc::ptr_eq(rc, &self.0)
441            });
442            previous_sibling_borrow.next_sibling = Some(new_sibling.0);
443        } else {
444            // No previous sibling.
445            if let Some(parent_ref) = self_borrow.parent.as_ref() {
446                if let Some(parent_strong) = parent_ref.upgrade() {
447                    let mut parent_borrow = parent_strong.borrow_mut();
448                    parent_borrow.first_child = Some(new_sibling.0);
449                }
450            }
451        }
452    }
453
454    pub fn from_html(html: Html) -> Option<Self> {
455        match html {
456            Html::Comment { .. } => None,
457            Html::Text { text } => Some(DomNode::create_text(text)),
458            Html::Element {
459                tag,
460                attributes,
461                children,
462            } => {
463                let node = DomNode::create_element_with_attributes(tag, attributes);
464                for c in children {
465                    if let Some(n) = DomNode::from_html(c) {
466                        node.append_child(n);
467                    }
468                }
469                Some(node)
470            }
471        }
472    }
473}
474
475/// Escapes HTML special characters in text content
476fn escape_html(text: &str) -> String {
477    text.chars()
478        .map(|c| match c {
479            '&' => "&amp;".to_string(),
480            '<' => "&lt;".to_string(),
481            '>' => "&gt;".to_string(),
482            '"' => "&quot;".to_string(),
483            '\'' => "&#39;".to_string(),
484            _ => c.to_string(),
485        })
486        .collect()
487}
488impl std::fmt::Display for DomNode {
489    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
490        match &*self.kind() {
491            DomNodeKind::Text { text } => write!(f, "{}", escape_html(text)),
492            DomNodeKind::Element { tag, attributes } => {
493                let attributes = attributes
494                    .iter()
495                    .map(|(k, v)| {
496                        if !v.is_empty() {
497                            format!(r#"{k}="{v}""#)
498                        } else {
499                            k.into()
500                        }
501                    })
502                    .collect::<Vec<String>>()
503                    .join(" ");
504
505                let spacing = if !attributes.is_empty() {
506                    String::from(" ")
507                } else {
508                    String::new()
509                };
510
511                let children: Vec<DomNode> = self.children().collect();
512                if children.is_empty() && is_void_element(tag) {
513                    return write!(f, "<{tag}{spacing}{}/>", attributes);
514                }
515
516                let mut content = String::new();
517
518                for c in children {
519                    content += &format!("{}", c);
520                }
521
522                write!(f, "<{tag}{spacing}{}>{}</{tag}>", attributes, content)
523            }
524        }
525    }
526}
527
528/// Cloning a `WeakNode` only increments a reference count. It does not copy the data.
529impl Clone for WeakDomNode {
530    fn clone(&self) -> Self {
531        WeakDomNode(Weak::clone(&self.0))
532    }
533}
534
535impl fmt::Debug for WeakDomNode {
536    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
537        f.write_str("(WeakNode)")
538    }
539}
540
541impl WeakDomNode {
542    /// Attempts to upgrade the WeakNode to a Node.
543    pub fn upgrade(&self) -> Option<DomNode> {
544        self.0.upgrade().map(DomNode)
545    }
546}
547
548impl DomNodeData {
549    /// Detaches a node from its parent and siblings. Children are not affected.
550    fn detach(&mut self) {
551        let parent_weak = self.parent.take();
552        let previous_sibling_weak = self.previous_sibling.take();
553        let next_sibling_strong = self.next_sibling.take();
554
555        let previous_sibling_opt = previous_sibling_weak
556            .as_ref()
557            .and_then(|weak| weak.upgrade());
558
559        if let Some(next_sibling_ref) = next_sibling_strong.as_ref() {
560            let mut next_sibling_borrow = next_sibling_ref.borrow_mut();
561            next_sibling_borrow.previous_sibling = previous_sibling_weak;
562        } else if let Some(parent_ref) = parent_weak.as_ref() {
563            if let Some(parent_strong) = parent_ref.upgrade() {
564                let mut parent_borrow = parent_strong.borrow_mut();
565                parent_borrow.last_child = previous_sibling_weak;
566            }
567        }
568
569        if let Some(previous_sibling_strong) = previous_sibling_opt {
570            let mut previous_sibling_borrow = previous_sibling_strong.borrow_mut();
571            previous_sibling_borrow.next_sibling = next_sibling_strong;
572        } else if let Some(parent_ref) = parent_weak.as_ref() {
573            if let Some(parent_strong) = parent_ref.upgrade() {
574                let mut parent_borrow = parent_strong.borrow_mut();
575                parent_borrow.first_child = next_sibling_strong;
576            }
577        }
578    }
579}
580
581impl Drop for DomNodeData {
582    fn drop(&mut self) {
583        // Collect all descendant nodes and detach them to prevent the stack overflow.
584
585        let mut stack = Vec::new();
586        if let Some(first_child) = self.first_child.as_ref() {
587            // Create `Node` from `NodeData`.
588            let first_child = DomNode(first_child.clone());
589            // Iterate `self` children, without creating yet another `Node`.
590            for child1 in first_child.following_siblings() {
591                for child2 in child1.descendants() {
592                    stack.push(child2);
593                }
594            }
595        }
596
597        for node in stack {
598            node.detach();
599        }
600    }
601}
602
603macro_rules! impl_node_iterator {
604    ($name: ident, $next: expr) => {
605        impl Iterator for $name {
606            type Item = DomNode;
607
608            /// # Panics
609            ///
610            /// Panics if the node about to be yielded is currently mutably borrowed.
611            fn next(&mut self) -> Option<Self::Item> {
612                match self.0.take() {
613                    Some(node) => {
614                        self.0 = $next(&node);
615                        Some(node)
616                    }
617                    None => None,
618                }
619            }
620        }
621    };
622}
623
624/// An iterator of nodes to the ancestors a given node.
625pub struct Ancestors(Option<DomNode>);
626impl_node_iterator!(Ancestors, |node: &DomNode| node.parent());
627
628/// An iterator of nodes to the siblings before a given node.
629pub struct PrecedingSiblings(Option<DomNode>);
630impl_node_iterator!(PrecedingSiblings, |node: &DomNode| node.previous_sibling());
631
632/// An iterator of nodes to the siblings after a given node.
633pub struct FollowingSiblings(Option<DomNode>);
634impl_node_iterator!(FollowingSiblings, |node: &DomNode| node.next_sibling());
635
636/// A double ended iterator of nodes to the children of a given node.
637pub struct Children {
638    next: Option<DomNode>,
639    next_back: Option<DomNode>,
640}
641
642impl Children {
643    // true if self.next_back's next sibling is self.next
644    fn finished(&self) -> bool {
645        match self.next_back {
646            Some(ref next_back) => next_back.next_sibling() == self.next,
647            _ => true,
648        }
649    }
650}
651
652impl Iterator for Children {
653    type Item = DomNode;
654
655    /// # Panics
656    ///
657    /// Panics if the node about to be yielded is currently mutably borrowed.
658    fn next(&mut self) -> Option<Self::Item> {
659        if self.finished() {
660            return None;
661        }
662
663        match self.next.take() {
664            Some(node) => {
665                self.next = node.next_sibling();
666                Some(node)
667            }
668            None => None,
669        }
670    }
671}
672
673impl DoubleEndedIterator for Children {
674    /// # Panics
675    ///
676    /// Panics if the node about to be yielded is currently mutably borrowed.
677    fn next_back(&mut self) -> Option<Self::Item> {
678        if self.finished() {
679            return None;
680        }
681
682        match self.next_back.take() {
683            Some(node) => {
684                self.next_back = node.previous_sibling();
685                Some(node)
686            }
687            None => None,
688        }
689    }
690}
691
692/// An iterator of nodes to a given node and its descendants, in tree order.
693pub struct Descendants(Traverse);
694
695impl Iterator for Descendants {
696    type Item = DomNode;
697
698    /// # Panics
699    ///
700    /// Panics if the node about to be yielded is currently mutably borrowed.
701    fn next(&mut self) -> Option<Self::Item> {
702        loop {
703            match self.0.next() {
704                Some(NodeEdge::Start(node)) => return Some(node),
705                Some(NodeEdge::End(_)) => {}
706                None => return None,
707            }
708        }
709    }
710}
711
712/// A node type during traverse.
713#[derive(Clone, Debug)]
714pub enum NodeEdge {
715    /// Indicates that start of a node that has children.
716    /// Yielded by `Traverse::next` before the node's descendants.
717    /// In HTML or XML, this corresponds to an opening tag like `<div>`
718    Start(DomNode),
719
720    /// Indicates that end of a node that has children.
721    /// Yielded by `Traverse::next` after the node's descendants.
722    /// In HTML or XML, this corresponds to a closing tag like `</div>`
723    End(DomNode),
724}
725
726// Implement PartialEq manually, because we do not need to require T: PartialEq
727impl PartialEq for NodeEdge {
728    fn eq(&self, other: &NodeEdge) -> bool {
729        match (self, other) {
730            (NodeEdge::Start(n1), NodeEdge::Start(n2)) => *n1 == *n2,
731            (NodeEdge::End(n1), NodeEdge::End(n2)) => *n1 == *n2,
732            _ => false,
733        }
734    }
735}
736
737impl NodeEdge {
738    fn next_item(&self, root: &DomNode) -> Option<NodeEdge> {
739        match *self {
740            NodeEdge::Start(ref node) => match node.first_child() {
741                Some(first_child) => Some(NodeEdge::Start(first_child)),
742                None => Some(NodeEdge::End(node.clone())),
743            },
744            NodeEdge::End(ref node) => {
745                if *node == *root {
746                    None
747                } else {
748                    match node.next_sibling() {
749                        Some(next_sibling) => Some(NodeEdge::Start(next_sibling)),
750                        // `node.parent()` here can only be `None`
751                        // if the tree has been modified during iteration,
752                        // but silently stopping iteration
753                        // seems a more sensible behavior than panicking.
754                        None => node.parent().map(NodeEdge::End),
755                    }
756                }
757            }
758        }
759    }
760
761    fn previous_item(&self, root: &DomNode) -> Option<NodeEdge> {
762        match *self {
763            NodeEdge::End(ref node) => match node.last_child() {
764                Some(last_child) => Some(NodeEdge::End(last_child)),
765                None => Some(NodeEdge::Start(node.clone())),
766            },
767            NodeEdge::Start(ref node) => {
768                if *node == *root {
769                    None
770                } else {
771                    match node.previous_sibling() {
772                        Some(previous_sibling) => Some(NodeEdge::End(previous_sibling)),
773                        // `node.parent()` here can only be `None`
774                        // if the tree has been modified during iteration,
775                        // but silently stopping iteration
776                        // seems a more sensible behavior than panicking.
777                        None => node.parent().map(NodeEdge::Start),
778                    }
779                }
780            }
781        }
782    }
783}
784
785/// A double ended iterator of nodes to a given node and its descendants,
786/// in tree order.
787pub struct Traverse {
788    root: DomNode,
789    next: Option<NodeEdge>,
790    next_back: Option<NodeEdge>,
791}
792
793impl Traverse {
794    // true if self.next_back's next item is self.next
795    fn finished(&self) -> bool {
796        match self.next_back {
797            Some(ref next_back) => next_back.next_item(&self.root) == self.next,
798            _ => true,
799        }
800    }
801}
802
803impl Iterator for Traverse {
804    type Item = NodeEdge;
805
806    /// # Panics
807    ///
808    /// Panics if the node about to be yielded is currently mutably borrowed.
809    fn next(&mut self) -> Option<Self::Item> {
810        if self.finished() {
811            return None;
812        }
813
814        match self.next.take() {
815            Some(item) => {
816                self.next = item.next_item(&self.root);
817                Some(item)
818            }
819            None => None,
820        }
821    }
822}
823
824impl DoubleEndedIterator for Traverse {
825    /// # Panics
826    ///
827    /// Panics if the node about to be yielded is currently mutably borrowed.
828    fn next_back(&mut self) -> Option<Self::Item> {
829        if self.finished() {
830            return None;
831        }
832
833        match self.next_back.take() {
834            Some(item) => {
835                self.next_back = item.previous_item(&self.root);
836                Some(item)
837            }
838            None => None,
839        }
840    }
841}