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