xml_no_std/
reader.rs

1//! Contains high-level interface for a pull-based XML parser.
2//!
3//! The most important type in this module is `EventReader`, which provides an iterator
4//! view for events in XML document.
5
6use core::iter::FusedIterator;
7use core::result;
8
9use crate::common::{Position, TextPosition};
10
11pub use self::config::ParserConfig;
12pub use self::config::ParserConfig2;
13pub use self::error::{Error, ErrorKind};
14pub use self::events::XmlEvent;
15
16use self::parser::PullParser;
17
18mod config;
19mod events;
20mod lexer;
21mod parser;
22mod error;
23
24
25/// A result type yielded by `XmlReader`.
26pub type Result<T, E = Error> = result::Result<T, E>;
27
28/// A wrapper around an Iterator which provides pull-based XML parsing.
29pub struct EventReader<'a, S: Iterator<Item = &'a u8>> {
30    source: S,
31    parser: PullParser,
32}
33
34impl<'a, S: Iterator<Item = &'a u8>> EventReader<'a, S> {
35    /// Creates a new reader from an Iterator.
36    #[inline]
37    pub fn new(source: S) -> EventReader<'a, S> {
38        EventReader::new_with_config(source, ParserConfig2::new())
39    }
40
41    /// Creates a new reader with the provided configuration from an Iterator.
42    #[inline]
43    pub fn new_with_config(source: S, config: impl Into<ParserConfig2>) -> EventReader<'a, S> {
44        EventReader { source, parser: PullParser::new(config) }
45    }
46
47    /// Pulls and returns next XML event from the Iterator.
48    ///
49    /// If returned event is `XmlEvent::Error` or `XmlEvent::EndDocument`, then
50    /// further calls to this method will return this event again.
51    #[inline]
52    pub fn next(&mut self) -> Result<XmlEvent> {
53        self.parser.next(&mut self.source)
54    }
55
56    /// Skips all XML events until the next end tag at the current level.
57    ///
58    /// Convenience function that is useful for the case where you have
59    /// encountered a start tag that is of no interest and want to
60    /// skip the entire XML subtree until the corresponding end tag.
61    #[inline]
62    pub fn skip(&mut self) -> Result<()> {
63        let mut depth = 1;
64
65        while depth > 0 {
66            match self.next()? {
67                XmlEvent::StartElement { .. } => depth += 1,
68                XmlEvent::EndElement { .. } => depth -= 1,
69                XmlEvent::EndDocument => return Err(Error {
70                    kind: ErrorKind::UnexpectedEof,
71                    pos: self.parser.position(),
72                }),
73                _ => {},
74            }
75        }
76
77        Ok(())
78    }
79
80    pub fn source(&self) -> &S { &self.source }
81    pub fn source_mut(&mut self) -> &mut S { &mut self.source }
82
83    /// Unwraps this `EventReader`, returning the underlying Iterator.
84    pub fn into_inner(self) -> S {
85        self.source
86    }
87}
88
89impl<'a, S: Iterator<Item = &'a u8>> Position for EventReader<'a, S> {
90    /// Returns the position of the last event produced by the reader.
91    #[inline]
92    fn position(&self) -> TextPosition {
93        self.parser.position()
94    }
95}
96
97impl<'a, S: Iterator<Item = &'a u8>> IntoIterator for EventReader<'a, S> {
98    type Item = Result<XmlEvent>;
99    type IntoIter = Events<'a, S>;
100
101    fn into_iter(self) -> Events<'a, S> {
102        Events { reader: self, finished: false }
103    }
104}
105
106/// An iterator over XML events created from some type implementing `Iterator<Item = &u8>`.
107///
108/// When the next event is `xml_no_std::event::Error` or `xml_no_std::event::EndDocument`, then
109/// it will be returned by the iterator once, and then it will stop producing events.
110pub struct Events<'a, S: Iterator<Item = &'a u8>> {
111    reader: EventReader<'a, S>,
112    finished: bool,
113}
114
115impl<'a, S: Iterator<Item = &'a u8>> Events<'a, S> {
116    /// Unwraps the iterator, returning the internal `EventReader`.
117    #[inline]
118    pub fn into_inner(self) -> EventReader<'a, S> {
119        self.reader
120    }
121
122    pub fn source(&self) -> &S { &self.reader.source }
123    pub fn source_mut(&mut self) -> &mut S { &mut self.reader.source }
124
125}
126
127impl<'a, S: Iterator<Item = &'a u8>> FusedIterator for Events<'a, S> {
128}
129
130impl<'a, S: Iterator<Item = &'a u8>> Iterator for Events<'a, S> {
131    type Item = Result<XmlEvent>;
132
133    #[inline]
134    fn next(&mut self) -> Option<Result<XmlEvent>> {
135        if self.finished && !self.reader.parser.is_ignoring_end_of_stream() {
136            None
137        } else {
138            let ev = self.reader.next();
139            if let Ok(XmlEvent::EndDocument) | Err(_) = ev {
140                self.finished = true;
141            }
142            Some(ev)
143        }
144    }
145}
146
147impl<'a> EventReader<'a, core::slice::Iter<'a, u8>> {
148    /// A convenience method to create an `XmlReader` from a string slice.
149    #[inline]
150    #[must_use]
151    pub fn from_str(source: &str) -> EventReader<core::slice::Iter<u8>> {
152        EventReader::new(source.as_bytes().into_iter())
153    }
154}