xsd_parser/quick_xml/reader/
mod.rs1mod error_reader;
5mod io_reader;
6mod slice_reader;
7
8#[cfg(feature = "async")]
9mod fut;
10
11#[cfg(feature = "async")]
12use std::future::Future;
13
14use std::borrow::Cow;
15use std::cell::RefCell;
16use std::mem::take;
17
18use quick_xml::{
19 events::Event,
20 name::{LocalName, PrefixDeclaration, PrefixIter, QName, ResolveResult},
21};
22
23use crate::xml::NamespacesShared;
24
25pub use self::error_reader::ErrorReader;
26pub use self::io_reader::IoReader;
27pub use self::slice_reader::SliceReader;
28
29#[cfg(feature = "async")]
30pub use self::fut::{ReadTag, SkipCurrent};
31
32use super::{Error, ErrorKind};
33
34pub trait XmlReader: Sized {
36 fn resolve<'n>(&self, name: QName<'n>, attribute: bool) -> (ResolveResult<'_>, LocalName<'n>);
38
39 fn namespaces(&self) -> NamespacesShared<'static>;
41
42 fn current_position(&self) -> u64;
44
45 fn error_position(&self) -> u64;
47
48 fn extend_error(&self, error: Error) -> Error {
50 error.with_pos(self.error_position())
51 }
52
53 fn map_error<E>(&self, error: E) -> Error
56 where
57 Error: From<E>,
58 {
59 self.extend_error(Error::from(error))
60 }
61
62 #[allow(clippy::missing_errors_doc)]
64 fn map_result<T, E>(&self, result: Result<T, E>) -> Result<T, Error>
65 where
66 Error: From<E>,
67 {
68 result.map_err(|error| self.map_error(error))
69 }
70
71 #[allow(clippy::missing_errors_doc)]
73 fn err<E>(&self, error: E) -> Result<(), Error>
74 where
75 Error: From<E>,
76 {
77 Err(self.map_error(error))
78 }
79
80 fn with_error_info(self) -> ErrorReader<Self> {
82 ErrorReader::new(self)
83 }
84}
85
86pub trait XmlReaderSync<'a>: XmlReader {
88 fn read_event(&mut self) -> Result<Event<'a>, Error>;
94
95 fn read_tag(&mut self) -> Result<Event<'a>, Error> {
102 loop {
103 if let e @ (Event::Start(_) | Event::Empty(_) | Event::End(_)) = self.read_event()? {
104 break Ok(e);
105 }
106 }
107 }
108
109 fn skip_current(&mut self) -> Result<(), Error> {
115 let mut depth = 0usize;
116
117 loop {
118 let event = self.read_event()?;
119
120 match event {
121 Event::Start(_) => depth += 1,
122 Event::End(_) if depth == 1 => return Ok(()),
123 Event::End(_) => depth -= 1,
124 Event::Eof => Err(ErrorKind::UnexpectedEof)?,
125 _ if depth > 0 => (),
126 _ => return Ok(()),
127 }
128 }
129 }
130}
131
132#[cfg(feature = "async")]
134pub trait XmlReaderAsync<'a>: XmlReader {
135 type ReadEventFut<'x>: Future<Output = Result<Event<'a>, Error>> + Unpin
137 where
138 Self: 'x;
139
140 fn read_event_async(&mut self) -> Self::ReadEventFut<'_>;
142
143 fn read_tag_async(&mut self) -> ReadTag<'a, '_, Self> {
146 ReadTag::new(self)
147 }
148
149 fn skip_current_async(&mut self) -> SkipCurrent<'a, '_, Self> {
152 SkipCurrent::new(self)
153 }
154}
155
156#[derive(Default, Debug)]
157struct NamespacesBuilder(RefCell<NamespacesBuilderState>);
158
159#[derive(Debug)]
160struct NamespacesBuilderState {
161 level: usize,
162 pending: bool,
163 elements: Vec<(usize, Option<NamespacesShared<'static>>)>,
164}
165
166impl NamespacesBuilder {
167 fn get_or_create(&self, prefixes: PrefixIter<'_>) -> NamespacesShared<'static> {
168 let mut state = self.0.borrow_mut();
169
170 state
171 .elements
172 .last_mut()
173 .map(|(_, x)| {
174 let prefixes = prefixes.map(|(decl, ns)| {
175 let key = match decl {
176 PrefixDeclaration::Default => Cow::Owned(Vec::new()),
177 PrefixDeclaration::Named(x) => Cow::Owned(x.into()),
178 };
179 let value = Cow::Owned(ns.0.into());
180
181 (key, value)
182 });
183
184 x.get_or_insert_with(|| NamespacesShared::new(prefixes.collect()))
185 .clone()
186 })
187 .unwrap_or_default()
188 }
189
190 fn handle_event(&self, event: &Event<'_>) {
191 let mut state = self.0.borrow_mut();
192
193 if take(&mut state.pending) {
194 state.level = state.level.saturating_sub(1);
195
196 loop {
197 if matches!(state.elements.last(), Some((last_level, _)) if *last_level > state.level)
198 {
199 state.elements.pop();
200 } else {
201 break;
202 }
203 }
204 }
205
206 match event {
207 Event::Start(start) | Event::Empty(start) => {
208 state.level += 1;
209 state.pending = matches!(event, Event::Empty(_));
210
211 for a in start.attributes().with_checks(false).flatten() {
212 if a.key.0.starts_with(b"xmlns") {
213 let level = state.level;
214
215 state.elements.push((level, None));
216
217 break;
218 }
219 }
220 }
221 Event::End(_) => {
222 state.pending = true;
223 }
224 _ => (),
225 }
226 }
227}
228
229impl Default for NamespacesBuilderState {
230 fn default() -> Self {
231 Self {
232 level: 0,
233 pending: false,
234 elements: vec![(0, None)],
235 }
236 }
237}