1 //! Error management module
2 
3 /// The error type used by this crate.
4 #[derive(Debug)]
5 pub enum Error {
6     /// IO error
7     Io(::std::io::Error),
8     /// Utf8 error
9     Utf8(::std::str::Utf8Error),
10     /// Unexpected End of File
11     UnexpectedEof(String),
12     /// End event mismatch
13     EndEventMismatch {
14         /// Expected end event
15         expected: String,
16         /// Found end event
17         found: String,
18     },
19     /// Unexpected token
20     UnexpectedToken(String),
21     /// Unexpected <!>
22     UnexpectedBang,
23     /// Text not found, expected `Event::Text`
24     TextNotFound,
25     /// `Event::XmlDecl` must start with *version* attribute
26     XmlDeclWithoutVersion(Option<String>),
27     /// Attribute Name contains quote
28     NameWithQuote(usize),
29     /// Attribute key not followed by with `=`
30     NoEqAfterName(usize),
31     /// Attribute value not quoted
32     UnquotedValue(usize),
33     /// Duplicate attribute
34     DuplicatedAttribute(usize, usize),
35     /// Escape error
36     EscapeError(::escape::EscapeError),
37 }
38 
39 impl From<::std::io::Error> for Error {
40     /// Creates a new `Error::Io` from the given error
41     #[inline]
from(error: ::std::io::Error) -> Error42     fn from(error: ::std::io::Error) -> Error {
43         Error::Io(error)
44     }
45 }
46 
47 impl From<::std::str::Utf8Error> for Error {
48     /// Creates a new `Error::Utf8` from the given error
49     #[inline]
from(error: ::std::str::Utf8Error) -> Error50     fn from(error: ::std::str::Utf8Error) -> Error {
51         Error::Utf8(error)
52     }
53 }
54 
55 /// A specialized `Result` type where the error is hard-wired to [`Error`].
56 ///
57 /// [`Error`]: enum.Error.html
58 pub type Result<T> = ::std::result::Result<T, Error>;
59 
60 impl std::fmt::Display for Error {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result61     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
62         match self {
63             Error::Io(e) => write!(f, "I/O error: {}", e),
64             Error::Utf8(e) => write!(f, "UTF8 error: {}", e),
65             Error::UnexpectedEof(e) => write!(f, "Unexpected EOF during reading {}.", e),
66             Error::EndEventMismatch { expected, found } => {
67                 write!(f, "Expecting </{}> found </{}>", expected, found)
68             }
69             Error::UnexpectedToken(e) => write!(f, "Unexpected token '{}'", e),
70             Error::UnexpectedBang => write!(
71                 f,
72                 "Only Comment, CDATA and DOCTYPE nodes can start with a '!'"
73             ),
74             Error::TextNotFound => write!(f, "Cannot read text, expecting Event::Text"),
75             Error::XmlDeclWithoutVersion(e) => write!(
76                 f,
77                 "XmlDecl must start with 'version' attribute, found {:?}",
78                 e
79             ),
80             Error::NameWithQuote(e) => write!(
81                 f,
82                 "error while parsing attribute at position {}: \
83                  Attribute key cannot contain quote.",
84                 e
85             ),
86             Error::NoEqAfterName(e) => write!(
87                 f,
88                 "error while parsing attribute at position {}: \
89                  Attribute key must be directly followed by = or space",
90                 e
91             ),
92             Error::UnquotedValue(e) => write!(
93                 f,
94                 "error while parsing attribute at position {}: \
95                  Attribute value must start with a quote.",
96                 e
97             ),
98             Error::DuplicatedAttribute(pos1, pos2) => write!(
99                 f,
100                 "error while parsing attribute at position {0}: \
101                  Duplicate attribute at position {1} and {0}",
102                 pos1, pos2
103             ),
104             Error::EscapeError(e) => write!(f, "{}", e),
105         }
106     }
107 }
108 
109 impl std::error::Error for Error {
source(&self) -> Option<&(dyn std::error::Error + 'static)>110     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
111         match self {
112             Error::Io(e) => Some(e),
113             Error::Utf8(e) => Some(e),
114             Error::EscapeError(e) => Some(e),
115             _ => None,
116         }
117     }
118 }
119 
120 #[cfg(feature = "serialize")]
121 pub mod serialize {
122     //! A module to handle serde (de)serialization errors
123 
124     use super::Error;
125     use std::fmt;
126 
127     /// (De)serialization error
128     #[derive(Debug)]
129     pub enum DeError {
130         /// Serde custom error
131         Custom(String),
132         /// Cannot parse to integer
133         Int(std::num::ParseIntError),
134         /// Cannot parse to float
135         Float(std::num::ParseFloatError),
136         /// Xml parsing error
137         Xml(Error),
138         /// Unexpected end of attributes
139         EndOfAttributes,
140         /// Unexpected end of file
141         Eof,
142         /// Invalid value for a boolean
143         InvalidBoolean(String),
144         /// Invalid unit value
145         InvalidUnit(String),
146         /// Invalid event for Enum
147         InvalidEnum(crate::events::Event<'static>),
148         /// Expecting Text event
149         Text,
150         /// Expecting Start event
151         Start,
152         /// Expecting End event
153         End,
154         /// Unsupported operation
155         Unsupported(&'static str),
156     }
157 
158     impl fmt::Display for DeError {
fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>159         fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
160             match self {
161                 DeError::Custom(s) => write!(f, "{}", s),
162                 DeError::Xml(e) => write!(f, "{}", e),
163                 DeError::Int(e) => write!(f, "{}", e),
164                 DeError::Float(e) => write!(f, "{}", e),
165                 DeError::EndOfAttributes => write!(f, "Unexpected end of attributes"),
166                 DeError::Eof => write!(f, "Unexpected `Event::Eof`"),
167                 DeError::InvalidBoolean(v) => write!(f, "Invalid boolean value '{}'", v),
168                 DeError::InvalidUnit(v) => {
169                     write!(f, "Invalid unit value '{}', expected empty string", v)
170                 }
171                 DeError::InvalidEnum(e) => write!(
172                     f,
173                     "Invalid event for Enum, expecting Text or Start, got: {:?}",
174                     e
175                 ),
176                 DeError::Text => write!(f, "Expecting Text event"),
177                 DeError::Start => write!(f, "Expecting Start event"),
178                 DeError::End => write!(f, "Expecting End event"),
179                 DeError::Unsupported(s) => write!(f, "Unsupported operation {}", s),
180             }
181         }
182     }
183 
184     impl ::std::error::Error for DeError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>185         fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
186             match self {
187                 DeError::Int(e) => Some(e),
188                 DeError::Float(e) => Some(e),
189                 DeError::Xml(e) => Some(e),
190                 _ => None,
191             }
192         }
193     }
194 
195     impl serde::de::Error for DeError {
custom<T: fmt::Display>(msg: T) -> Self196         fn custom<T: fmt::Display>(msg: T) -> Self {
197             DeError::Custom(msg.to_string())
198         }
199     }
200 
201     impl serde::ser::Error for DeError {
custom<T: fmt::Display>(msg: T) -> Self202         fn custom<T: fmt::Display>(msg: T) -> Self {
203             DeError::Custom(msg.to_string())
204         }
205     }
206 
207     impl From<Error> for DeError {
from(e: Error) -> Self208         fn from(e: Error) -> Self {
209             DeError::Xml(e)
210         }
211     }
212 
213     impl From<std::num::ParseIntError> for DeError {
from(e: std::num::ParseIntError) -> Self214         fn from(e: std::num::ParseIntError) -> Self {
215             DeError::Int(e)
216         }
217     }
218 
219     impl From<std::num::ParseFloatError> for DeError {
from(e: std::num::ParseFloatError) -> Self220         fn from(e: std::num::ParseFloatError) -> Self {
221             DeError::Float(e)
222         }
223     }
224 }
225