| 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 | |