xsd_parser/quick_xml/
error.rs

1use std::error::Error as StdError;
2use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
3use std::mem::take;
4use std::str::Utf8Error;
5
6use quick_xml::events::attributes::AttrError;
7use quick_xml::{events::Event, Error as XmlError};
8use thiserror::Error;
9
10use crate::misc::RawByteStr;
11
12/// Quick XML Error
13#[derive(Debug)]
14pub struct Error {
15    /// Detailed information about the actual error.
16    pub kind: Kind,
17
18    /// Cursor position inside the XML document where the error occurred.
19    pub position: Option<u64>,
20
21    /// Path of XML tags where the error occurred.
22    pub elements: Option<Vec<String>>,
23}
24
25/// Quick XML error kind.
26#[derive(Debug, Error)]
27pub enum Kind {
28    /// Error forwarded from the [`quick_xml`] crate.
29    #[error("XML Error: message={0}")]
30    XmlError(#[from] XmlError),
31
32    /// Attribute error forwarded from the [`quick_xml`] crate.
33    #[error("Attribute Error: message={0}")]
34    AttrError(#[from] AttrError),
35
36    /// Invalid UTF-8 string.
37    #[error("UTF-8 Error: message={0}")]
38    InvalidUtf8(#[from] Utf8Error),
39
40    /// Duplicate attribute.
41    ///
42    /// The attribute was expected only once.
43    #[error("Duplicated attribute: name={0}")]
44    DuplicateAttribute(RawByteStr),
45
46    /// Duplicate element.
47    ///
48    /// The element was expected only once.
49    #[error("Duplicated element: name={0}")]
50    DuplicateElement(RawByteStr),
51
52    /// Unexpected attribute.
53    ///
54    /// The attribute was not expected for the current element.
55    #[error("Unexpected attribute: name={0}")]
56    UnexpectedAttribute(RawByteStr),
57
58    /// Missing attribute.
59    ///
60    /// The attribute was expected to be present, but it was not.
61    #[error("Missing attribute: name={0}")]
62    MissingAttribute(RawByteStr),
63
64    /// Missing element.
65    ///
66    /// The element was expected to be present, but it was not.
67    #[error("Missing element: name={0}")]
68    MissingElement(RawByteStr),
69
70    /// Invalid data.
71    #[error("Invalid data: `{0}`")]
72    InvalidData(RawByteStr),
73
74    /// Missing content.
75    ///
76    /// The element was expected to have some content, but it haven't.
77    #[error("Missing content")]
78    MissingContent,
79
80    /// Duplicate content.
81    ///
82    /// The content was expected only once.
83    #[error("Duplicate content")]
84    DuplicateContent,
85
86    /// Missing name.
87    ///
88    /// The serializer is not able to set a default name for the specified value.
89    #[error("Missing name")]
90    MissingName,
91
92    /// Unknown or invalid value.
93    #[error("Unknown or invalid value: {0}")]
94    UnknownOrInvalidValue(RawByteStr),
95
96    /// Insufficient size.
97    ///
98    /// The element or attribute contains less items then expected.
99    #[error("Insufficient size (min={min}, max={max}, actual={actual})")]
100    InsufficientSize {
101        /// Smallest expected index.
102        min: usize,
103
104        /// Largest expected index.
105        max: usize,
106
107        /// Actual index.
108        actual: usize,
109    },
110
111    /// Invalid union.
112    #[error("Invalid union: {0}")]
113    InvalidUnion(UnionError),
114
115    /// Custom error.
116    ///
117    /// Can store any kind of error.
118    #[error("Custom Error: message={0}")]
119    Custom(Box<dyn StdError + Send + Sync>),
120
121    /// Unexpected [`quick_xml`] event.
122    #[error("Unexpected event: {0:#?}!")]
123    UnexpectedEvent(Event<'static>),
124
125    /// Unexpected end of file.
126    #[error("Unexpected EoF!")]
127    UnexpectedEof,
128}
129
130impl Error {
131    /// Create a new error that uses [`Kind::Custom`] to store the passed `error`.
132    pub fn custom<E: StdError + Send + Sync + 'static>(error: E) -> Self {
133        Kind::Custom(Box::new(error)).into()
134    }
135
136    pub(super) fn new<E>(error: E) -> Self
137    where
138        Kind: From<E>,
139    {
140        Self {
141            kind: Kind::from(error),
142            position: None,
143            elements: None,
144        }
145    }
146
147    pub(super) fn with_pos(mut self, position: u64) -> Self {
148        self.position = Some(position);
149
150        self
151    }
152
153    pub(super) fn with_error_info(mut self, info: &ErrorInfo) -> Self {
154        self.elements = Some(info.elements.clone());
155
156        self
157    }
158}
159
160impl<E> From<E> for Error
161where
162    Kind: From<E>,
163{
164    fn from(error: E) -> Self {
165        Self::new(error)
166    }
167}
168
169impl Display for Error {
170    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
171        write!(f, "{}", &self.kind)?;
172
173        if let Some(pos) = &self.position {
174            write!(f, "; position={}", pos)?;
175        }
176
177        if let Some(elements) = &self.elements {
178            let mut first = true;
179
180            for element in elements {
181                if take(&mut first) {
182                    write!(f, "; element={}", element)?;
183                } else {
184                    write!(f, ">{}", element)?;
185                }
186            }
187        }
188
189        Ok(())
190    }
191}
192
193impl StdError for Error {}
194
195/// Contains the different errors that occurred when deserializing a union.
196pub struct UnionError(Vec<Box<dyn StdError + Send + Sync + 'static>>);
197
198impl<X> From<X> for UnionError
199where
200    X: IntoIterator,
201    X::Item: StdError + Send + Sync + 'static,
202{
203    fn from(value: X) -> Self {
204        Self(
205            value
206                .into_iter()
207                .map(|err| -> Box<dyn StdError + Send + Sync + 'static> { Box::new(err) })
208                .collect(),
209        )
210    }
211}
212
213impl Debug for UnionError {
214    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
215        for err in &self.0 {
216            write!(f, "- {err}")?;
217        }
218
219        Ok(())
220    }
221}
222
223impl Display for UnionError {
224    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
225        for err in &self.0 {
226            write!(f, "- {err}")?;
227        }
228
229        Ok(())
230    }
231}
232
233#[derive(Default, Debug)]
234pub(super) struct ErrorInfo {
235    elements: Vec<String>,
236}
237
238impl ErrorInfo {
239    pub(super) fn update(&mut self, event: &Event<'_>) {
240        match event {
241            Event::Start(x) => {
242                self.elements
243                    .push(String::from_utf8_lossy(x.name().0).to_string());
244            }
245            Event::End(_) => {
246                self.elements.pop();
247            }
248            _ => (),
249        }
250    }
251}