1 | //! Error management module
|
2 |
|
3 | use crate::escape::EscapeError;
|
4 | use crate::events::attributes::AttrError;
|
5 | use crate::utils::write_byte_string;
|
6 | use std::fmt;
|
7 | use std::io::Error as IoError;
|
8 | use std::str::Utf8Error;
|
9 | use std::string::FromUtf8Error;
|
10 | use std::sync::Arc;
|
11 |
|
12 | /// The error type used by this crate.
|
13 | #[derive (Clone, Debug)]
|
14 | pub 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 |
|
52 | impl 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 |
|
60 | impl 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 |
|
68 | impl 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 |
|
76 | impl 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 |
|
84 | impl 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`].
|
92 | pub type Result<T> = std::result::Result<T, Error>;
|
93 |
|
94 | impl 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 |
|
128 | impl 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" )]
|
141 | pub 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 | |