xsd_parser/quick_xml/reader/
error_reader.rs

1use quick_xml::{
2    events::Event,
3    name::{LocalName, PrefixIter, QName, ResolveResult},
4};
5
6use crate::quick_xml::{error::ErrorInfo, Error};
7
8use super::{XmlReader, XmlReaderSync};
9
10/// Implements a [`XmlReader`] that is able to provide additional error
11/// information like the current cursor position or the chain of currently
12/// processed XML tags.
13#[derive(Debug)]
14pub struct ErrorReader<R> {
15    inner: R,
16    error_info: ErrorInfo,
17    current_pos: u64,
18}
19
20impl<R> ErrorReader<R>
21where
22    R: XmlReader,
23{
24    /// Create a new [`ErrorReader`] instance from the passed reader.
25    pub fn new(inner: R) -> Self {
26        Self {
27            inner,
28            error_info: ErrorInfo::default(),
29            current_pos: 0,
30        }
31    }
32
33    /// Extracts the internal reader from the instance.
34    pub fn into_inner(self) -> R {
35        self.inner
36    }
37}
38
39impl<R> XmlReader for ErrorReader<R>
40where
41    R: XmlReader,
42{
43    fn resolve<'n>(&self, name: QName<'n>, attribute: bool) -> (ResolveResult<'_>, LocalName<'n>) {
44        self.inner.resolve(name, attribute)
45    }
46
47    fn prefixes(&self) -> PrefixIter<'_> {
48        self.inner.prefixes()
49    }
50
51    fn current_position(&self) -> u64 {
52        self.inner.current_position()
53    }
54
55    fn error_position(&self) -> u64 {
56        self.inner.error_position()
57    }
58
59    fn extend_error(&self, error: Error) -> Error {
60        let error = self.inner.extend_error(error);
61        let mut pos = self.error_position();
62        if pos == 0 {
63            pos = self.current_pos;
64        }
65        if pos == 0 {
66            pos = self.current_position();
67        }
68
69        error.with_pos(pos).with_error_info(&self.error_info)
70    }
71}
72
73impl<'a, R> XmlReaderSync<'a> for ErrorReader<R>
74where
75    R: XmlReaderSync<'a>,
76{
77    fn read_event(&mut self) -> Result<Event<'a>, Error> {
78        self.current_pos = self.inner.current_position();
79
80        match self.inner.read_event() {
81            Ok(event) => {
82                self.error_info.update(&event);
83
84                Ok(event)
85            }
86            Err(error) => Err(self.extend_error(error)),
87        }
88    }
89}
90
91#[cfg(feature = "async")]
92impl<'a, R> super::XmlReaderAsync<'a> for ErrorReader<R>
93where
94    R: super::XmlReaderAsync<'a>,
95    for<'x> R::ReadEventFut<'x>: Unpin,
96{
97    type ReadEventFut<'x>
98        = ReadEventFut<'a, 'x, R>
99    where
100        R: 'x;
101
102    fn read_event_async(&mut self) -> Self::ReadEventFut<'_> {
103        ReadEventFut::new(self)
104    }
105}
106
107/// Implements a [`Future`] that is emitted by the [`XmlReaderAsync::read_event_async`]
108/// implementation of the [`ErrorReader`].
109#[derive(Debug)]
110#[cfg(feature = "async")]
111pub struct ReadEventFut<'a, 'x, R>
112where
113    R: super::XmlReaderAsync<'a> + 'x,
114{
115    inner: R::ReadEventFut<'x>,
116    error_info: &'x mut ErrorInfo,
117}
118
119#[cfg(feature = "async")]
120impl<'a, 'x, R> ReadEventFut<'a, 'x, R>
121where
122    R: super::XmlReaderAsync<'a> + 'x,
123{
124    fn new(reader: &'x mut ErrorReader<R>) -> Self {
125        let inner = reader.inner.read_event_async();
126        let error_info = &mut reader.error_info;
127
128        Self { inner, error_info }
129    }
130}
131
132#[cfg(feature = "async")]
133impl<'a, 'x, R> std::future::Future for ReadEventFut<'a, 'x, R>
134where
135    Self: Unpin,
136    R: super::XmlReaderAsync<'a> + 'x,
137    R::ReadEventFut<'x>: Unpin,
138{
139    type Output = Result<Event<'a>, Error>;
140
141    fn poll(
142        self: std::pin::Pin<&mut Self>,
143        cx: &mut std::task::Context<'_>,
144    ) -> std::task::Poll<Self::Output> {
145        use futures::ready;
146        use std::pin::Pin;
147        use std::task::Poll;
148
149        let this = self.get_mut();
150
151        Poll::Ready(match ready!(Pin::new(&mut this.inner).poll(cx)) {
152            Ok(event) => {
153                this.error_info.update(&event);
154
155                Ok(event)
156            }
157            Err(error) => Err(error.with_error_info(this.error_info)),
158        })
159    }
160}