Thanks to visit codestin.com
Credit goes to docs.rs

html_parser/dom/
node.rs

1use super::element::Element;
2use serde::Serialize;
3
4#[derive(Debug, Clone, Serialize, PartialEq)]
5#[serde(untagged)]
6pub enum Node {
7    Text(String),
8    Element(Element),
9    Comment(String),
10}
11
12impl Node {
13    pub fn text(&self) -> Option<&str> {
14        match self {
15            Node::Text(t) => Some(t.as_str()),
16            _ => None,
17        }
18    }
19
20    pub fn element(&self) -> Option<&Element> {
21        match self {
22            Node::Element(e) => Some(e),
23            _ => None,
24        }
25    }
26
27    pub fn comment(&self) -> Option<&str> {
28        match self {
29            Node::Comment(t) => Some(t.as_str()),
30            _ => None,
31        }
32    }
33}
34
35impl<'a> IntoIterator for &'a Node {
36    type Item = &'a Node;
37    type IntoIter = NodeIntoIterator<'a>;
38
39    fn into_iter(self) -> Self::IntoIter {
40        NodeIntoIterator {
41            node: self,
42            index: vec![],
43        }
44    }
45}
46
47pub struct NodeIntoIterator<'a> {
48    node: &'a Node,
49    // We add/remove to this vec each time we go up/down a node three
50    index: Vec<(usize, &'a Node)>,
51}
52
53impl<'a> Iterator for NodeIntoIterator<'a> {
54    type Item = &'a Node;
55
56    fn next(&mut self) -> Option<Self::Item> {
57        // Get first child
58        let child = match self.node {
59            Node::Element(ref e) => e.children.get(0),
60            _ => None,
61        };
62
63        let result = match child {
64            // If element has child, return child
65            Some(child) => {
66                self.index.push((0, self.node));
67                self.node = child;
68                Some(child)
69            }
70            // If element doesn't have a child, but is a child of another node
71            None if self.index.len() > 0 => {
72                let mut has_finished = false;
73                let mut next_node = None;
74
75                while !has_finished {
76                    // Try to get the next sibling of the parent node
77                    if let Some((sibling_index, parent)) = self.index.pop() {
78                        let next_sibling = sibling_index + 1;
79                        let sibling = if let Node::Element(ref e) = parent {
80                            e.children.get(next_sibling)
81                        } else {
82                            None
83                        };
84                        if sibling.is_some() {
85                            has_finished = true;
86                            self.index.push((next_sibling, parent));
87                            next_node = sibling;
88                        } else {
89                            continue;
90                        }
91                    // Break of there are no more parents
92                    } else {
93                        has_finished = true;
94                    }
95                }
96
97                if let Some(next_node) = next_node {
98                    self.node = next_node;
99                }
100
101                next_node
102            }
103            _ => None,
104        };
105
106        result
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn node_utillity_functions() {
116        let node = Node::Text("test".to_string());
117
118        assert_eq!(node.text(), Some("test"));
119        assert_eq!(node.element(), None);
120        assert_eq!(node.comment(), None);
121
122        let node = Node::Element(Element::default());
123
124        assert_eq!(node.text(), None);
125        assert_eq!(node.element(), Some(&Element::default()));
126        assert_eq!(node.comment(), None);
127
128        let node = Node::Comment("test".to_string());
129
130        assert_eq!(node.text(), None);
131        assert_eq!(node.element(), None);
132        assert_eq!(node.comment(), Some("test"));
133    }
134}