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}