xsd_parser/quick_xml/
error.rs

1use std::error::Error as StdError;
2use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
3use std::io::Error as IoError;
4use std::mem::take;
5use std::str::Utf8Error;
6
7use quick_xml::{
8    encoding::EncodingError,
9    escape::EscapeError,
10    events::{attributes::AttrError, Event},
11    Error as XmlError,
12};
13use thiserror::Error;
14
15use crate::models::RawByteStr;
16
17/// Quick XML Error
18#[derive(Debug)]
19pub struct Error {
20    /// Detailed information about the actual error.
21    pub kind: Kind,
22
23    /// Cursor position inside the XML document where the error occurred.
24    pub position: Option<u64>,
25
26    /// Path of XML tags where the error occurred.
27    pub elements: Option<Vec<String>>,
28}
29
30/// Quick XML error kind.
31#[derive(Debug, Error)]
32pub enum Kind {
33    /// Error forwarded from the [`quick_xml`] crate.
34    #[error("IO Error: message={0}")]
35    IoError(
36        #[from]
37        #[source]
38        IoError,
39    ),
40
41    /// Error forwarded from the [`quick_xml`] crate.
42    #[error("XML Error: message={0}")]
43    XmlError(
44        #[from]
45        #[source]
46        XmlError,
47    ),
48
49    /// Attribute error forwarded from the [`quick_xml`] crate.
50    #[error("Attribute Error: message={0}")]
51    AttrError(
52        #[from]
53        #[source]
54        AttrError,
55    ),
56
57    /// Invalid UTF-8 string.
58    #[error("UTF-8 Error: message={0}")]
59    InvalidUtf8(
60        #[from]
61        #[source]
62        Utf8Error,
63    ),
64
65    /// Escape Error
66    #[error("Escape Error: message={0}")]
67    EscapeError(
68        #[from]
69        #[source]
70        EscapeError,
71    ),
72
73    /// Encoding Error
74    #[error("Encoding Error: message={0}")]
75    EncodingError(
76        #[from]
77        #[source]
78        EncodingError,
79    ),
80
81    /// Duplicate attribute.
82    ///
83    /// The attribute was expected only once.
84    #[error("Duplicated attribute: name={0}")]
85    DuplicateAttribute(RawByteStr),
86
87    /// Duplicate element.
88    ///
89    /// The element was expected only once.
90    #[error("Duplicated element: name={0}")]
91    DuplicateElement(RawByteStr),
92
93    /// Unexpected attribute.
94    ///
95    /// The attribute was not expected for the current element.
96    #[error("Unexpected attribute: name={0}")]
97    UnexpectedAttribute(RawByteStr),
98
99    /// Missing attribute.
100    ///
101    /// The attribute was expected to be present, but it was not.
102    #[error("Missing attribute: name={0}")]
103    MissingAttribute(RawByteStr),
104
105    /// Missing element.
106    ///
107    /// The element was expected to be present, but it was not.
108    #[error("Missing element: name={0}")]
109    MissingElement(RawByteStr),
110
111    /// Invalid data.
112    #[error("Invalid data: `{0}`")]
113    InvalidData(RawByteStr),
114
115    /// Invalid value.
116    #[error("Invalid value `{0}`: {1}")]
117    InvalidValue(RawByteStr, ValidateError),
118
119    /// Missing content.
120    ///
121    /// The element was expected to have some content, but it haven't.
122    #[error("Missing content")]
123    MissingContent,
124
125    /// Duplicate content.
126    ///
127    /// The content was expected only once.
128    #[error("Duplicate content")]
129    DuplicateContent,
130
131    /// Missing any element.
132    ///
133    /// The element was expected to have at least one `xs:any` element, but it haven't.
134    #[error("Missing any element")]
135    MissingAnyElement,
136
137    /// Duplicate content.
138    ///
139    /// The `xs:any` element is only expected once.
140    #[error("Duplicate any element")]
141    DuplicateAnyElement,
142
143    /// Missing name.
144    ///
145    /// The serializer is not able to set a default name for the specified value.
146    #[error("Missing name")]
147    MissingName,
148
149    /// Unknown or invalid value.
150    #[error("Unknown or invalid value: {0}")]
151    UnknownOrInvalidValue(RawByteStr),
152
153    /// Insufficient size.
154    ///
155    /// The element or attribute contains less items then expected.
156    #[error("Insufficient size (min={min}, max={max}, actual={actual})")]
157    InsufficientSize {
158        /// Smallest expected index.
159        min: usize,
160
161        /// Largest expected index.
162        max: usize,
163
164        /// Actual index.
165        actual: usize,
166    },
167
168    /// Invalid union.
169    #[error("Invalid union: {0}")]
170    InvalidUnion(UnionError),
171
172    /// Custom error.
173    ///
174    /// Can store any kind of error.
175    #[error("Custom Error: message={0}")]
176    Custom(Box<dyn StdError + Send + Sync>),
177
178    /// Unexpected [`quick_xml`] event.
179    #[error("Unexpected event: {0:#?}!")]
180    UnexpectedEvent(Event<'static>),
181
182    /// Unexpected end of file.
183    #[error("Unexpected EoF!")]
184    UnexpectedEof,
185}
186
187/// Error raised by different XML value validation functions.
188#[derive(Debug, Error)]
189pub enum ValidateError {
190    /// Value is not a valid decimal.
191    #[error("Value is not a valid decimal!")]
192    InvalidDecimalValue,
193
194    /// The string value is too short.
195    #[error("Value is shorter then {0} characters!")]
196    MinLength(usize),
197
198    /// The string value is too large.
199    #[error("Value is longer than {0} characters!")]
200    MaxLength(usize),
201
202    /// The string value does not match the expected pattern.
203    #[error("Value does not match the expected pattern `{0}`!")]
204    Pattern(&'static str),
205
206    /// The decimal value has too much total digits.
207    #[error("Value has more then {0} total digits!")]
208    TotalDigits(usize),
209
210    /// The decimal value has too much fraction digits.
211    #[error("Value has more then {0} fraction digits!")]
212    FractionDigits(usize),
213
214    /// The decimal value is less than the expected range.
215    ///
216    /// Range is defined by `xs:minInclusive`.
217    #[error("Value is less then `{0}`!")]
218    LessThan(&'static str),
219
220    /// The decimal value is less or equal than the expected range.
221    ///
222    /// Range is defined by `xs:minExclusive`.
223    #[error("Value is less or equal then `{0}`!")]
224    LessEqualThan(&'static str),
225
226    /// The decimal value is greater than the expected range.
227    ///
228    /// Range is defined by `xs:maxInclusive`.
229    #[error("Value is greater then `{0}`!")]
230    GraterThan(&'static str),
231
232    /// The decimal value is greater or equal than the expected range.
233    ///
234    /// Range is defined by `xs:maxExclusive`.
235    #[error("Value is greater equal then `{0}`!")]
236    GraterEqualThan(&'static str),
237}
238
239impl Error {
240    /// Create a new error that uses [`Kind::Custom`] to store the passed `error`.
241    pub fn custom<E: StdError + Send + Sync + 'static>(error: E) -> Self {
242        Kind::Custom(Box::new(error)).into()
243    }
244
245    pub(super) fn new<E>(error: E) -> Self
246    where
247        Kind: From<E>,
248    {
249        Self {
250            kind: Kind::from(error),
251            position: None,
252            elements: None,
253        }
254    }
255
256    pub(super) fn with_pos(mut self, position: u64) -> Self {
257        self.position = Some(position);
258
259        self
260    }
261
262    pub(super) fn with_error_info(mut self, info: &ErrorInfo) -> Self {
263        self.elements = Some(info.elements.clone());
264
265        self
266    }
267}
268
269impl<E> From<E> for Error
270where
271    Kind: From<E>,
272{
273    fn from(error: E) -> Self {
274        Self::new(error)
275    }
276}
277
278impl<'a> From<(&'a [u8], ValidateError)> for Error {
279    fn from((value, error): (&'a [u8], ValidateError)) -> Self {
280        Self::new(Kind::InvalidValue(RawByteStr::from_slice(value), error))
281    }
282}
283
284impl Display for Error {
285    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
286        write!(f, "{}", &self.kind)?;
287
288        if let Some(pos) = &self.position {
289            write!(f, "; position={}", pos)?;
290        }
291
292        if let Some(elements) = &self.elements {
293            let mut first = true;
294
295            for element in elements {
296                if take(&mut first) {
297                    write!(f, "; element={}", element)?;
298                } else {
299                    write!(f, ">{}", element)?;
300                }
301            }
302        }
303
304        Ok(())
305    }
306}
307
308impl StdError for Error {}
309
310/// Contains the different errors that occurred when deserializing a union.
311pub struct UnionError(Vec<Box<dyn StdError + Send + Sync + 'static>>);
312
313impl<X> From<X> for UnionError
314where
315    X: IntoIterator,
316    X::Item: StdError + Send + Sync + 'static,
317{
318    fn from(value: X) -> Self {
319        Self(
320            value
321                .into_iter()
322                .map(|err| -> Box<dyn StdError + Send + Sync + 'static> { Box::new(err) })
323                .collect(),
324        )
325    }
326}
327
328impl Debug for UnionError {
329    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
330        for err in &self.0 {
331            write!(f, "- {err}")?;
332        }
333
334        Ok(())
335    }
336}
337
338impl Display for UnionError {
339    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
340        for err in &self.0 {
341            write!(f, "- {err}")?;
342        }
343
344        Ok(())
345    }
346}
347
348#[derive(Default, Debug)]
349pub(super) struct ErrorInfo {
350    elements: Vec<String>,
351}
352
353impl ErrorInfo {
354    pub(super) fn update(&mut self, event: &Event<'_>) {
355        match event {
356            Event::Start(x) => {
357                self.elements
358                    .push(String::from_utf8_lossy(x.name().0).to_string());
359            }
360            Event::End(_) => {
361                self.elements.pop();
362            }
363            _ => (),
364        }
365    }
366}