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(data: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: &Arc) => Some(e),
132 Error::NonDecodable(Some(e: &Utf8Error)) => Some(e),
133 Error::InvalidAttr(e: &AttrError) => Some(e),
134 Error::EscapeError(e: &EscapeError) => 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}
323