fast_xml/
errors.rs

1//! Error management module
2
3use crate::escape::EscapeError;
4use crate::events::attributes::AttrError;
5use std::str::Utf8Error;
6
7/// The error type used by this crate.
8#[derive(Debug)]
9pub enum Error {
10    /// IO error
11    Io(::std::io::Error),
12    /// Utf8 error
13    Utf8(Utf8Error),
14    /// Unexpected End of File
15    UnexpectedEof(String),
16    /// End event mismatch
17    EndEventMismatch {
18        /// Expected end event
19        expected: String,
20        /// Found end event
21        found: String,
22    },
23    /// Unexpected token
24    UnexpectedToken(String),
25    /// Unexpected <!>
26    UnexpectedBang(u8),
27    /// Text not found, expected `Event::Text`
28    TextNotFound,
29    /// `Event::XmlDecl` must start with *version* attribute
30    XmlDeclWithoutVersion(Option<String>),
31    /// Attribute parsing error
32    InvalidAttr(AttrError),
33    /// Escape error
34    EscapeError(EscapeError),
35}
36
37impl From<::std::io::Error> for Error {
38    /// Creates a new `Error::Io` from the given error
39    #[inline]
40    fn from(error: ::std::io::Error) -> Error {
41        Error::Io(error)
42    }
43}
44
45impl From<Utf8Error> for Error {
46    /// Creates a new `Error::Utf8` from the given error
47    #[inline]
48    fn from(error: Utf8Error) -> Error {
49        Error::Utf8(error)
50    }
51}
52
53impl From<EscapeError> for Error {
54    /// Creates a new `Error::EscapeError` from the given error
55    #[inline]
56    fn from(error: EscapeError) -> Error {
57        Error::EscapeError(error)
58    }
59}
60
61impl From<AttrError> for Error {
62    #[inline]
63    fn from(error: AttrError) -> Self {
64        Error::InvalidAttr(error)
65    }
66}
67
68/// A specialized `Result` type where the error is hard-wired to [`Error`].
69///
70/// [`Error`]: enum.Error.html
71pub type Result<T> = std::result::Result<T, Error>;
72
73impl std::fmt::Display for Error {
74    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
75        match self {
76            Error::Io(e) => write!(f, "I/O error: {}", e),
77            Error::Utf8(e) => write!(f, "UTF8 error: {}", e),
78            Error::UnexpectedEof(e) => write!(f, "Unexpected EOF during reading {}", e),
79            Error::EndEventMismatch { expected, found } => {
80                write!(f, "Expecting </{}> found </{}>", expected, found)
81            }
82            Error::UnexpectedToken(e) => write!(f, "Unexpected token '{}'", e),
83            Error::UnexpectedBang(b) => write!(
84                f,
85                "Only Comment (`--`), CDATA (`[CDATA[`) and DOCTYPE (`DOCTYPE`) nodes can start with a '!', but symbol `{}` found",
86                *b as char
87            ),
88            Error::TextNotFound => write!(f, "Cannot read text, expecting Event::Text"),
89            Error::XmlDeclWithoutVersion(e) => write!(
90                f,
91                "XmlDecl must start with 'version' attribute, found {:?}",
92                e
93            ),
94            Error::InvalidAttr(e) => write!(f, "error while parsing attribute: {}", e),
95            Error::EscapeError(e) => write!(f, "{}", e),
96        }
97    }
98}
99
100impl std::error::Error for Error {
101    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
102        match self {
103            Error::Io(e) => Some(e),
104            Error::Utf8(e) => Some(e),
105            Error::InvalidAttr(e) => Some(e),
106            Error::EscapeError(e) => Some(e),
107            _ => None,
108        }
109    }
110}
111
112#[cfg(feature = "serialize")]
113pub mod serialize {
114    //! A module to handle serde (de)serialization errors
115
116    use super::*;
117    use crate::utils::write_byte_string;
118    use std::fmt;
119    use std::num::{ParseFloatError, ParseIntError};
120
121    /// (De)serialization error
122    #[derive(Debug)]
123    pub enum DeError {
124        /// Serde custom error
125        Custom(String),
126        /// Xml parsing error
127        InvalidXml(Error),
128        /// Cannot parse to integer
129        InvalidInt(ParseIntError),
130        /// Cannot parse to float
131        InvalidFloat(ParseFloatError),
132        /// Cannot parse specified value to boolean
133        InvalidBoolean(String),
134        /// This error indicates an error in the [`Deserialize`](serde::Deserialize)
135        /// implementation when read a map or a struct: `MapAccess::next_value[_seed]`
136        /// was called before `MapAccess::next_key[_seed]`.
137        ///
138        /// You should check your types, that implements corresponding trait.
139        KeyNotRead,
140        /// Deserializer encounter a start tag with a specified name when it is
141        /// not expecting. This happens when you try to deserialize a primitive
142        /// value (numbers, strings, booleans) from an XML element.
143        UnexpectedStart(Vec<u8>),
144        /// Deserializer encounter an end tag with a specified name when it is
145        /// not expecting. Usually that should not be possible, because XML reader
146        /// is not able to produce such stream of events that lead to this error.
147        ///
148        /// If you get this error this likely indicates and error in the `fast_xml`.
149        /// Please open an issue at <https://github.com/Mingun/fast-xml>, provide
150        /// your Rust code and XML input.
151        UnexpectedEnd(Vec<u8>),
152        /// Unexpected end of file
153        UnexpectedEof,
154        /// This error indicates that [`deserialize_struct`] was called, but there
155        /// is no any XML element in the input. That means that you try to deserialize
156        /// a struct not from an XML element.
157        ///
158        /// [`deserialize_struct`]: serde::de::Deserializer::deserialize_struct
159        ExpectedStart,
160        /// Unsupported operation
161        Unsupported(&'static str),
162    }
163
164    impl fmt::Display for DeError {
165        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166            match self {
167                DeError::Custom(s) => write!(f, "{}", s),
168                DeError::InvalidXml(e) => write!(f, "{}", e),
169                DeError::InvalidInt(e) => write!(f, "{}", e),
170                DeError::InvalidFloat(e) => write!(f, "{}", e),
171                DeError::InvalidBoolean(v) => write!(f, "Invalid boolean value '{}'", v),
172                DeError::KeyNotRead => write!(f, "Invalid `Deserialize` implementation: `MapAccess::next_value[_seed]` was called before `MapAccess::next_key[_seed]`"),
173                DeError::UnexpectedStart(e) => {
174                    f.write_str("Unexpected `Event::Start(")?;
175                    write_byte_string(f, &e)?;
176                    f.write_str(")`")
177                }
178                DeError::UnexpectedEnd(e) => {
179                    f.write_str("Unexpected `Event::End(")?;
180                    write_byte_string(f, &e)?;
181                    f.write_str(")`")
182                }
183                DeError::UnexpectedEof => write!(f, "Unexpected `Event::Eof`"),
184                DeError::ExpectedStart => write!(f, "Expecting `Event::Start`"),
185                DeError::Unsupported(s) => write!(f, "Unsupported operation {}", s),
186            }
187        }
188    }
189
190    impl ::std::error::Error for DeError {
191        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
192            match self {
193                DeError::InvalidXml(e) => Some(e),
194                DeError::InvalidInt(e) => Some(e),
195                DeError::InvalidFloat(e) => Some(e),
196                _ => None,
197            }
198        }
199    }
200
201    impl serde::de::Error for DeError {
202        fn custom<T: fmt::Display>(msg: T) -> Self {
203            DeError::Custom(msg.to_string())
204        }
205    }
206
207    impl serde::ser::Error for DeError {
208        fn custom<T: fmt::Display>(msg: T) -> Self {
209            DeError::Custom(msg.to_string())
210        }
211    }
212
213    impl From<Error> for DeError {
214        fn from(e: Error) -> Self {
215            Self::InvalidXml(e)
216        }
217    }
218
219    impl From<EscapeError> for DeError {
220        #[inline]
221        fn from(e: EscapeError) -> Self {
222            Self::InvalidXml(e.into())
223        }
224    }
225
226    impl From<ParseIntError> for DeError {
227        fn from(e: ParseIntError) -> Self {
228            Self::InvalidInt(e)
229        }
230    }
231
232    impl From<ParseFloatError> for DeError {
233        fn from(e: ParseFloatError) -> Self {
234            Self::InvalidFloat(e)
235        }
236    }
237
238    impl From<AttrError> for DeError {
239        #[inline]
240        fn from(e: AttrError) -> Self {
241            Self::InvalidXml(e.into())
242        }
243    }
244}