quick_xml/
errors.rs

1//! Error management module
2
3use crate::escape::EscapeError;
4use crate::events::attributes::AttrError;
5use crate::utils::write_byte_string;
6use std::fmt;
7use std::io::Error as IoError;
8use std::str::Utf8Error;
9use std::string::FromUtf8Error;
10use std::sync::Arc;
11
12/// The error type used by this crate.
13#[derive(Clone, Debug)]
14pub enum Error {
15    /// XML document cannot be read from or written to underlying source.
16    ///
17    /// Contains the reference-counted I/O error to make the error type `Clone`able.
18    Io(Arc<IoError>),
19    /// Input decoding error. If [`encoding`] feature is disabled, contains `None`,
20    /// otherwise contains the UTF-8 decoding error
21    ///
22    /// [`encoding`]: index.html#encoding
23    NonDecodable(Option<Utf8Error>),
24    /// Unexpected End of File
25    UnexpectedEof(String),
26    /// End event mismatch
27    EndEventMismatch {
28        /// Expected end event
29        expected: String,
30        /// Found end event
31        found: String,
32    },
33    /// Unexpected token
34    UnexpectedToken(String),
35    /// Unexpected <!>
36    UnexpectedBang(u8),
37    /// Text not found, expected `Event::Text`
38    TextNotFound,
39    /// `Event::BytesDecl` must start with *version* attribute. Contains the attribute
40    /// that was found or `None` if an xml declaration doesn't contain attributes.
41    XmlDeclWithoutVersion(Option<String>),
42    /// Empty `Event::DocType`. `<!doctype foo>` is correct but `<!doctype > is not.
43    ///
44    /// See <https://www.w3.org/TR/xml11/#NT-doctypedecl>
45    EmptyDocType,
46    /// Attribute parsing error
47    InvalidAttr(AttrError),
48    /// Escape error
49    EscapeError(EscapeError),
50    /// Specified namespace prefix is unknown, cannot resolve namespace for it
51    UnknownPrefix(Vec<u8>),
52    /// Error for when a reserved namespace is set incorrectly.
53    ///
54    /// This error returned in following cases:
55    /// - the XML document attempts to bind `xml` prefix to something other than
56    ///   `http://www.w3.org/XML/1998/namespace`
57    /// - the XML document attempts to bind `xmlns` prefix
58    /// - the XML document attempts to bind some prefix (except `xml`) to
59    ///   `http://www.w3.org/XML/1998/namespace`
60    /// - the XML document attempts to bind some prefix to
61    ///   `http://www.w3.org/2000/xmlns/`
62    InvalidPrefixBind {
63        /// The prefix that is tried to be bound
64        prefix: Vec<u8>,
65        /// Namespace to which prefix tried to be bound
66        namespace: Vec<u8>,
67    },
68}
69
70impl From<IoError> for Error {
71    /// Creates a new `Error::Io` from the given error
72    #[inline]
73    fn from(error: IoError) -> Error {
74        Error::Io(Arc::new(error))
75    }
76}
77
78impl From<Utf8Error> for Error {
79    /// Creates a new `Error::NonDecodable` from the given error
80    #[inline]
81    fn from(error: Utf8Error) -> Error {
82        Error::NonDecodable(Some(error))
83    }
84}
85
86impl From<FromUtf8Error> for Error {
87    /// Creates a new `Error::Utf8` from the given error
88    #[inline]
89    fn from(error: FromUtf8Error) -> Error {
90        error.utf8_error().into()
91    }
92}
93
94impl From<EscapeError> for Error {
95    /// Creates a new `Error::EscapeError` from the given error
96    #[inline]
97    fn from(error: EscapeError) -> Error {
98        Error::EscapeError(error)
99    }
100}
101
102impl From<AttrError> for Error {
103    #[inline]
104    fn from(error: AttrError) -> Self {
105        Error::InvalidAttr(error)
106    }
107}
108
109/// A specialized `Result` type where the error is hard-wired to [`Error`].
110pub type Result<T> = std::result::Result<T, Error>;
111
112impl fmt::Display for Error {
113    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114        match self {
115            Error::Io(e) => write!(f, "I/O error: {}", e),
116            Error::NonDecodable(None) => write!(f, "Malformed input, decoding impossible"),
117            Error::NonDecodable(Some(e)) => write!(f, "Malformed UTF-8 input: {}", e),
118            Error::UnexpectedEof(e) => write!(f, "Unexpected EOF during reading {}", e),
119            Error::EndEventMismatch { expected, found } => {
120                write!(f, "Expecting </{}> found </{}>", expected, found)
121            }
122            Error::UnexpectedToken(e) => write!(f, "Unexpected token '{}'", e),
123            Error::UnexpectedBang(b) => write!(
124                f,
125                "Only Comment (`--`), CDATA (`[CDATA[`) and DOCTYPE (`DOCTYPE`) nodes can start with a '!', but symbol `{}` found",
126                *b as char
127            ),
128            Error::TextNotFound => write!(f, "Cannot read text, expecting Event::Text"),
129            Error::XmlDeclWithoutVersion(e) => write!(
130                f,
131                "XmlDecl must start with 'version' attribute, found {:?}",
132                e
133            ),
134            Error::EmptyDocType => write!(f, "DOCTYPE declaration must not be empty"),
135            Error::InvalidAttr(e) => write!(f, "error while parsing attribute: {}", e),
136            Error::EscapeError(e) => write!(f, "{}", e),
137            Error::UnknownPrefix(prefix) => {
138                f.write_str("Unknown namespace prefix '")?;
139                write_byte_string(f, prefix)?;
140                f.write_str("'")
141            }
142            Error::InvalidPrefixBind { prefix, namespace } => {
143                f.write_str("The namespace prefix '")?;
144                write_byte_string(f, prefix)?;
145                f.write_str("' cannot be bound to '")?;
146                write_byte_string(f, namespace)?;
147                f.write_str("'")
148            }
149        }
150    }
151}
152
153impl std::error::Error for Error {
154    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
155        match self {
156            Error::Io(e) => Some(e),
157            Error::NonDecodable(Some(e)) => Some(e),
158            Error::InvalidAttr(e) => Some(e),
159            Error::EscapeError(e) => Some(e),
160            _ => None,
161        }
162    }
163}
164
165#[cfg(feature = "serialize")]
166pub mod serialize {
167    //! A module to handle serde (de)serialization errors
168
169    use super::*;
170    use crate::utils::write_byte_string;
171    use std::borrow::Cow;
172    #[cfg(feature = "overlapped-lists")]
173    use std::num::NonZeroUsize;
174    use std::num::{ParseFloatError, ParseIntError};
175
176    /// (De)serialization error
177    #[derive(Clone, Debug)]
178    pub enum DeError {
179        /// Serde custom error
180        Custom(String),
181        /// Xml parsing error
182        InvalidXml(Error),
183        /// Cannot parse to integer
184        InvalidInt(ParseIntError),
185        /// Cannot parse to float
186        InvalidFloat(ParseFloatError),
187        /// Cannot parse specified value to boolean
188        InvalidBoolean(String),
189        /// This error indicates an error in the [`Deserialize`](serde::Deserialize)
190        /// implementation when read a map or a struct: `MapAccess::next_value[_seed]`
191        /// was called before `MapAccess::next_key[_seed]`.
192        ///
193        /// You should check your types, that implements corresponding trait.
194        KeyNotRead,
195        /// Deserializer encounter a start tag with a specified name when it is
196        /// not expecting. This happens when you try to deserialize a primitive
197        /// value (numbers, strings, booleans) from an XML element.
198        UnexpectedStart(Vec<u8>),
199        /// Deserializer encounter an end tag with a specified name when it is
200        /// not expecting. Usually that should not be possible, because XML reader
201        /// is not able to produce such stream of events that lead to this error.
202        ///
203        /// If you get this error this likely indicates and error in the `quick_xml`.
204        /// Please open an issue at <https://github.com/tafia/quick-xml>, provide
205        /// your Rust code and XML input.
206        UnexpectedEnd(Vec<u8>),
207        /// The [`Reader`] produced [`Event::Eof`] when it is not expecting,
208        /// for example, after producing [`Event::Start`] but before corresponding
209        /// [`Event::End`].
210        ///
211        /// [`Reader`]: crate::reader::Reader
212        /// [`Event::Eof`]: crate::events::Event::Eof
213        /// [`Event::Start`]: crate::events::Event::Start
214        /// [`Event::End`]: crate::events::Event::End
215        UnexpectedEof,
216        /// This error indicates that [`deserialize_struct`] was called, but there
217        /// is no any XML element in the input. That means that you try to deserialize
218        /// a struct not from an XML element.
219        ///
220        /// [`deserialize_struct`]: serde::de::Deserializer::deserialize_struct
221        ExpectedStart,
222        /// An attempt to deserialize to a type, that is not supported by the XML
223        /// store at current position, for example, attempt to deserialize `struct`
224        /// from attribute or attempt to deserialize binary data.
225        ///
226        /// Serialized type cannot be represented in an XML due to violation of the
227        /// XML rules in the final XML document. For example, attempt to serialize
228        /// a `HashMap<{integer}, ...>` would cause this error because [XML name]
229        /// cannot start from a digit or a hyphen (minus sign). The same result
230        /// would occur if map key is a complex type that cannot be serialized as
231        /// a primitive type (i.e. string, char, bool, unit struct or unit variant).
232        ///
233        /// [XML name]: https://www.w3.org/TR/xml11/#sec-common-syn
234        Unsupported(Cow<'static, str>),
235        /// Too many events were skipped while deserializing a sequence, event limit
236        /// exceeded. The limit was provided as an argument
237        #[cfg(feature = "overlapped-lists")]
238        TooManyEvents(NonZeroUsize),
239    }
240
241    impl fmt::Display for DeError {
242        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243            match self {
244                DeError::Custom(s) => write!(f, "{}", s),
245                DeError::InvalidXml(e) => write!(f, "{}", e),
246                DeError::InvalidInt(e) => write!(f, "{}", e),
247                DeError::InvalidFloat(e) => write!(f, "{}", e),
248                DeError::InvalidBoolean(v) => write!(f, "Invalid boolean value '{}'", v),
249                DeError::KeyNotRead => write!(f, "Invalid `Deserialize` implementation: `MapAccess::next_value[_seed]` was called before `MapAccess::next_key[_seed]`"),
250                DeError::UnexpectedStart(e) => {
251                    f.write_str("Unexpected `Event::Start(")?;
252                    write_byte_string(f, e)?;
253                    f.write_str(")`")
254                }
255                DeError::UnexpectedEnd(e) => {
256                    f.write_str("Unexpected `Event::End(")?;
257                    write_byte_string(f, e)?;
258                    f.write_str(")`")
259                }
260                DeError::UnexpectedEof => write!(f, "Unexpected `Event::Eof`"),
261                DeError::ExpectedStart => write!(f, "Expecting `Event::Start`"),
262                DeError::Unsupported(s) => write!(f, "Unsupported operation: {}", s),
263                #[cfg(feature = "overlapped-lists")]
264                DeError::TooManyEvents(s) => write!(f, "Deserializer buffers {} events, limit exceeded", s),
265            }
266        }
267    }
268
269    impl ::std::error::Error for DeError {
270        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
271            match self {
272                DeError::InvalidXml(e) => Some(e),
273                DeError::InvalidInt(e) => Some(e),
274                DeError::InvalidFloat(e) => Some(e),
275                _ => None,
276            }
277        }
278    }
279
280    impl serde::de::Error for DeError {
281        fn custom<T: fmt::Display>(msg: T) -> Self {
282            DeError::Custom(msg.to_string())
283        }
284    }
285
286    impl serde::ser::Error for DeError {
287        fn custom<T: fmt::Display>(msg: T) -> Self {
288            DeError::Custom(msg.to_string())
289        }
290    }
291
292    impl From<Error> for DeError {
293        #[inline]
294        fn from(e: Error) -> Self {
295            Self::InvalidXml(e)
296        }
297    }
298
299    impl From<EscapeError> for DeError {
300        #[inline]
301        fn from(e: EscapeError) -> Self {
302            Self::InvalidXml(e.into())
303        }
304    }
305
306    impl From<Utf8Error> for DeError {
307        #[inline]
308        fn from(e: Utf8Error) -> Self {
309            Self::InvalidXml(e.into())
310        }
311    }
312
313    impl From<FromUtf8Error> for DeError {
314        #[inline]
315        fn from(e: FromUtf8Error) -> Self {
316            Self::InvalidXml(e.into())
317        }
318    }
319
320    impl From<AttrError> for DeError {
321        #[inline]
322        fn from(e: AttrError) -> Self {
323            Self::InvalidXml(e.into())
324        }
325    }
326
327    impl From<ParseIntError> for DeError {
328        #[inline]
329        fn from(e: ParseIntError) -> Self {
330            Self::InvalidInt(e)
331        }
332    }
333
334    impl From<ParseFloatError> for DeError {
335        #[inline]
336        fn from(e: ParseFloatError) -> Self {
337            Self::InvalidFloat(e)
338        }
339    }
340
341    impl From<fmt::Error> for DeError {
342        #[inline]
343        fn from(e: fmt::Error) -> Self {
344            Self::Custom(e.to_string())
345        }
346    }
347}