xsd_parser/quick_xml/reader/
mod.rs

1//! Defines and implements different helper traits that are needed for the
2//! deserialization process with the [`quick_xml`] crate.
3
4mod 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
34/// Trait that defines the basics for an XML reader.
35pub trait XmlReader: Sized {
36    /// Resolves a qname in the current context of the XML file.
37    fn resolve<'n>(&self, name: QName<'n>, attribute: bool) -> (ResolveResult<'_>, LocalName<'n>);
38
39    /// Returns a map that contains all namespaces in the current context.
40    fn namespaces(&self) -> NamespacesShared<'static>;
41
42    /// Returns the current position (byte offset) in the current XML file.
43    fn current_position(&self) -> u64;
44
45    /// Returns the position (byte offset) of the last detected error.
46    fn error_position(&self) -> u64;
47
48    /// Add the error position to the passed error and return it.
49    fn extend_error(&self, error: Error) -> Error {
50        error.with_pos(self.error_position())
51    }
52
53    /// Converts the passed `error` to an [`Error`], adds the error information
54    /// using `extend_error` and returns it.
55    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    /// Same as `map_error`, but for the passed `result`.
63    #[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    /// Create a result from the passed `error` using `map_error` and returns it.
72    #[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    /// Wraps the current reader in a new [`ErrorReader`].
81    fn with_error_info(self) -> ErrorReader<Self> {
82        ErrorReader::new(self)
83    }
84}
85
86/// Trait that defines a synchronous XML reader.
87pub trait XmlReaderSync<'a>: XmlReader {
88    /// Reads the next [`Event`] from the reader.
89    ///
90    /// # Errors
91    ///
92    /// Returns an [`Error`] if the event could not been read.
93    fn read_event(&mut self) -> Result<Event<'a>, Error>;
94
95    /// Reads a new XML tag ([`Event::Start`], [`Event::Empty`] or [`Event::End`])
96    /// from the reader.
97    ///
98    /// # Errors
99    ///
100    /// Forwards the errors from `read_event`.
101    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    /// Skips the current event with respect to the level of the different XML tags.
110    ///
111    /// # Errors
112    ///
113    /// Forwards the errors from `read_event`.
114    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/// Trait that defines a asynchronous XML reader.
133#[cfg(feature = "async")]
134pub trait XmlReaderAsync<'a>: XmlReader {
135    /// Future that is returned by the [`read_event_async`] method.
136    type ReadEventFut<'x>: Future<Output = Result<Event<'a>, Error>> + Unpin
137    where
138        Self: 'x;
139
140    /// Reads the next [`Event`] from the reader asynchronously.
141    fn read_event_async(&mut self) -> Self::ReadEventFut<'_>;
142
143    /// Reads a new XML tag ([`Event::Start`], [`Event::Empty`] or [`Event::End`])
144    /// from the reader asynchronously.
145    fn read_tag_async(&mut self) -> ReadTag<'a, '_, Self> {
146        ReadTag::new(self)
147    }
148
149    /// Skips the current event with respect to the level of the different XML
150    /// tags asynchronously.
151    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}