1use std::io::Read;
7use std::iter::FusedIterator;
8use std::result;
9
10use crate::common::{Position, TextPosition};
11
12pub use self::config::ParserConfig;
13pub use self::error::{Error, ErrorKind};
14pub use self::events::XmlEvent;
15
16#[doc(hidden)]
18#[deprecated(note = "Merged into ParserConfig")]
19pub type ParserConfig2 = ParserConfig;
20
21use self::parser::PullParser;
22
23mod config;
24mod error;
25mod events;
26mod indexset;
27mod lexer;
28mod parser;
29
30pub type Result<T, E = Error> = result::Result<T, E>;
32
33pub struct EventReader<R: Read> {
37 source: R,
38 parser: PullParser,
39}
40
41impl<R: Read> EventReader<R> {
42 #[inline]
44 pub fn new(source: R) -> Self {
45 Self::new_with_config(source, ParserConfig::new())
46 }
47
48 #[inline]
50 pub fn new_with_config(source: R, config: impl Into<ParserConfig>) -> Self {
51 Self {
52 source,
53 parser: PullParser::new(config),
54 }
55 }
56
57 #[inline]
62 #[allow(clippy::should_implement_trait)]
63 pub fn next(&mut self) -> Result<XmlEvent> {
64 self.parser.next(&mut self.source)
65 }
66
67 #[inline]
73 pub fn skip(&mut self) -> Result<()> {
74 let mut depth = 1;
75
76 while depth > 0 {
77 match self.next()? {
78 XmlEvent::StartElement { .. } => depth += 1,
79 XmlEvent::EndElement { .. } => depth -= 1,
80 XmlEvent::EndDocument => return Err(Error {
81 kind: ErrorKind::UnexpectedEof,
82 pos: self.parser.position(),
83 }),
84 _ => {},
85 }
86 }
87
88 Ok(())
89 }
90
91 pub fn source(&self) -> &R { &self.source }
95
96 pub fn source_mut(&mut self) -> &mut R { &mut self.source }
100
101 pub fn into_inner(self) -> R {
107 self.source
108 }
109
110 #[inline]
114 #[deprecated(note = "there is `XmlEvent::Doctype` now")]
115 #[allow(deprecated)]
116 pub fn doctype(&self) -> Option<&str> {
117 self.parser.doctype()
118 }
119
120 #[inline]
128 pub fn add_entities<S: Into<String>, T: Into<String>>(&mut self, entities: impl IntoIterator<Item=(S, T)>) -> std::result::Result<(), crate::reader::error::ImmutableEntitiesError> {
129 self.parser.add_entities(entities)
130 }
131}
132
133impl<B: Read> Position for EventReader<B> {
134 #[inline]
136 fn position(&self) -> TextPosition {
137 self.parser.position()
138 }
139}
140
141impl<R: Read> IntoIterator for EventReader<R> {
142 type IntoIter = Events<R>;
143 type Item = Result<XmlEvent>;
144
145 fn into_iter(self) -> Events<R> {
146 Events { reader: self, finished: false }
147 }
148}
149
150pub struct Events<R: Read> {
155 reader: EventReader<R>,
156 finished: bool,
157}
158
159impl<R: Read> Events<R> {
160 #[inline]
162 pub fn into_inner(self) -> EventReader<R> {
163 self.reader
164 }
165
166 pub fn source(&self) -> &R { &self.reader.source }
170
171 pub fn source_mut(&mut self) -> &mut R { &mut self.reader.source }
175}
176
177impl<R: Read> std::ops::Deref for Events<R> {
178 type Target = EventReader<R>;
179
180 fn deref(&self) -> &Self::Target {
181 &self.reader
182 }
183}
184
185impl<R: Read> std::ops::DerefMut for Events<R> {
186 fn deref_mut(&mut self) -> &mut Self::Target {
187 &mut self.reader
188 }
189}
190
191impl<R: Read> FusedIterator for Events<R> {
192}
193
194impl<R: Read> Iterator for Events<R> {
195 type Item = Result<XmlEvent>;
196
197 #[inline]
198 fn next(&mut self) -> Option<Result<XmlEvent>> {
199 if self.finished && !self.reader.parser.is_ignoring_end_of_stream() {
200 None
201 } else {
202 let ev = self.reader.next();
203 if let Ok(XmlEvent::EndDocument) | Err(_) = ev {
204 self.finished = true;
205 }
206 Some(ev)
207 }
208 }
209}
210
211impl<'r> EventReader<&'r [u8]> {
212 #[inline]
214 #[must_use]
215 #[allow(clippy::should_implement_trait)]
216 pub fn from_str(source: &'r str) -> Self {
217 EventReader::new(source.as_bytes())
218 }
219}