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 quick_xml::{
15    events::Event,
16    name::{LocalName, PrefixIter, QName, ResolveResult},
17};
18
19pub use self::error_reader::ErrorReader;
20pub use self::io_reader::IoReader;
21pub use self::slice_reader::SliceReader;
22
23#[cfg(feature = "async")]
24pub use self::fut::{ReadTag, SkipCurrent};
25
26use super::{Error, ErrorKind};
27
28/// Trait that defines the basics for an XML reader.
29pub trait XmlReader: Sized {
30    /// Resolves a qname in the current context of the XML file.
31    fn resolve<'n>(&self, name: QName<'n>, attribute: bool) -> (ResolveResult<'_>, LocalName<'n>);
32
33    /// Returns an iterator the walks over all known namespace prefixes for the
34    /// current context of the XML file.
35    fn prefixes(&self) -> PrefixIter<'_>;
36
37    /// Returns the current position (byte offset) in the current XML file.
38    fn current_position(&self) -> u64;
39
40    /// Returns the position (byte offset) of the last detected error.
41    fn error_position(&self) -> u64;
42
43    /// Add the error position to the passed error and return it.
44    fn extend_error(&self, error: Error) -> Error {
45        error.with_pos(self.error_position())
46    }
47
48    /// Converts the passed `error` to an [`Error`], adds the error information
49    /// using `extend_error` and returns it.
50    fn map_error<E>(&self, error: E) -> Error
51    where
52        Error: From<E>,
53    {
54        self.extend_error(Error::from(error))
55    }
56
57    /// Same as `map_error`, but for the passed `result`.
58    #[allow(clippy::missing_errors_doc)]
59    fn map_result<T, E>(&self, result: Result<T, E>) -> Result<T, Error>
60    where
61        Error: From<E>,
62    {
63        result.map_err(|error| self.map_error(error))
64    }
65
66    /// Create a result from the passed `error` using `map_error` and returns it.
67    #[allow(clippy::missing_errors_doc)]
68    fn err<E>(&self, error: E) -> Result<(), Error>
69    where
70        Error: From<E>,
71    {
72        Err(self.map_error(error))
73    }
74
75    /// Wraps the current reader in a new [`ErrorReader`].
76    fn with_error_info(self) -> ErrorReader<Self> {
77        ErrorReader::new(self)
78    }
79}
80
81/// Trait that defines a synchronous XML reader.
82pub trait XmlReaderSync<'a>: XmlReader {
83    /// Reads the next [`Event`] from the reader.
84    ///
85    /// # Errors
86    ///
87    /// Returns an [`Error`] if the event could not been read.
88    fn read_event(&mut self) -> Result<Event<'a>, Error>;
89
90    /// Reads a new XML tag ([`Event::Start`], [`Event::Empty`] or [`Event::End`])
91    /// from the reader.
92    ///
93    /// # Errors
94    ///
95    /// Forwards the errors from `read_event`.
96    fn read_tag(&mut self) -> Result<Event<'a>, Error> {
97        loop {
98            if let e @ (Event::Start(_) | Event::Empty(_) | Event::End(_)) = self.read_event()? {
99                break Ok(e);
100            }
101        }
102    }
103
104    /// Skips the current event with respect to the level of the different XML tags.
105    ///
106    /// # Errors
107    ///
108    /// Forwards the errors from `read_event`.
109    fn skip_current(&mut self) -> Result<(), Error> {
110        let mut depth = 0usize;
111
112        loop {
113            let event = self.read_event()?;
114
115            match event {
116                Event::Start(_) => depth += 1,
117                Event::End(_) if depth == 1 => return Ok(()),
118                Event::End(_) => depth -= 1,
119                Event::Eof => Err(ErrorKind::UnexpectedEof)?,
120                _ if depth > 0 => (),
121                _ => return Ok(()),
122            }
123        }
124    }
125}
126
127/// Trait that defines a asynchronous XML reader.
128#[cfg(feature = "async")]
129pub trait XmlReaderAsync<'a>: XmlReader {
130    /// Future that is returned by the [`read_event_async`] method.
131    type ReadEventFut<'x>: Future<Output = Result<Event<'a>, Error>> + Unpin
132    where
133        Self: 'x;
134
135    /// Reads the next [`Event`] from the reader asynchronously.
136    fn read_event_async(&mut self) -> Self::ReadEventFut<'_>;
137
138    /// Reads a new XML tag ([`Event::Start`], [`Event::Empty`] or [`Event::End`])
139    /// from the reader asynchronously.
140    fn read_tag_async(&mut self) -> ReadTag<'a, '_, Self> {
141        ReadTag::new(self)
142    }
143
144    /// Skips the current event with respect to the level of the different XML
145    /// tags asynchronously.
146    fn skip_current_async(&mut self) -> SkipCurrent<'a, '_, Self> {
147        SkipCurrent::new(self)
148    }
149}