svg_nd/
svg_event.rs

1/*a Copyright
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7  http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14
15@file    svg_element_iter.rs
16@brief   Iterator over the SVG element
17 */
18
19//a Imports
20use super::SvgElement;
21
22//a XmlEvent
23//tp XmlEvent
24#[derive(Debug)]
25pub enum XmlEvent<'a> {
26    StartDocument,
27    EndDocument,
28    StartElement(&'a SvgElement),
29    EndElement(&'a SvgElement),
30    Characters(&'a SvgElement),
31}
32
33//ip XmlEvent
34impl<'a> XmlEvent<'a> {
35    pub fn as_xml(&self) -> String {
36        use XmlEvent::*;
37        match self {
38            StartDocument => r#"<?xml version="1.0" encoding="utf8"?>"#.into(),
39            EndDocument => "".into(),
40            StartElement(e) => {
41                let mut r = format!("<{}", e.name());
42                for (n, _op, v) in e.attributes() {
43                    r.push_str(&format!(r#" {}="{}""#, n, v));
44                }
45                r.push('>');
46                r
47            }
48            Characters(e) => e.characters().into(),
49            EndElement(e) => {
50                format!("</{}>", e.name())
51            }
52        }
53    }
54}
55
56//a SvgElement iterator
57//ti IterState
58#[derive(Debug)]
59enum IterState {
60    PreDocument,
61    PreElement,
62    PreString,
63    PreContent,
64    PostContent,
65    FindNextElement,
66    DocumentEnd,
67    Completed,
68}
69
70//tp ElementIter
71/// An iterator structure to permit iteration over an Svg object's elements
72pub struct ElementIter<'a> {
73    state: IterState,
74    elements: Vec<(&'a SvgElement, usize)>,
75}
76
77//ip ElementIter
78impl<'a> ElementIter<'a> {
79    //fp new
80    /// Create a new Svg element iterator
81    pub fn new(e: &'a SvgElement) -> Self {
82        let elements = vec![(e, 0)];
83        Self {
84            state: IterState::PreDocument,
85            elements,
86        }
87    }
88}
89
90//ip Iterator for ElementIter
91impl<'a> Iterator for ElementIter<'a> {
92    type Item = XmlEvent<'a>;
93    fn next(&mut self) -> Option<Self::Item> {
94        match self.state {
95            IterState::PreDocument => {
96                self.state = IterState::PreElement;
97                Some(XmlEvent::StartDocument)
98            }
99            IterState::PreElement => {
100                let (ele, n) = self.elements.pop().unwrap();
101                self.state = IterState::PreString;
102                self.elements.push((ele, n));
103                Some(XmlEvent::StartElement(ele))
104            }
105            IterState::PreString => {
106                let (ele, n) = self.elements.pop().unwrap();
107                self.state = IterState::PreContent;
108                if ele.characters() != "" {
109                    self.elements.push((ele, n));
110                    Some(XmlEvent::Characters(ele))
111                } else {
112                    self.elements.push((ele, n));
113                    self.next()
114                }
115            }
116            IterState::PreContent => {
117                let (ele, n) = self.elements.pop().unwrap();
118                if n < ele.contents().len() {
119                    let next_ele = &ele.contents()[n];
120                    self.elements.push((ele, n));
121                    self.elements.push((next_ele, 0));
122                    self.state = IterState::PreElement;
123                } else {
124                    self.state = IterState::PostContent;
125                    self.elements.push((ele, n));
126                }
127                self.next()
128            }
129            IterState::PostContent => {
130                let (ele, n) = self.elements.pop().unwrap();
131                self.state = IterState::FindNextElement;
132                self.elements.push((ele, n));
133                Some(XmlEvent::EndElement(ele))
134            }
135            IterState::FindNextElement => {
136                if self.elements.len() > 1 {
137                    let (_ele, _n) = self.elements.pop().unwrap();
138                    let (ele, n) = self.elements.pop().unwrap();
139                    if n + 1 < ele.contents().len() {
140                        let next_ele = &ele.contents()[n + 1];
141                        self.elements.push((ele, n + 1));
142                        self.elements.push((next_ele, 0));
143                        self.state = IterState::PreElement;
144                    } else {
145                        self.elements.push((ele, n + 1));
146                        self.state = IterState::PostContent;
147                    }
148                } else {
149                    self.state = IterState::DocumentEnd;
150                }
151                self.next()
152            }
153            IterState::DocumentEnd => {
154                self.state = IterState::Completed;
155                Some(XmlEvent::EndDocument)
156            }
157            IterState::Completed => None,
158        }
159    }
160}