1use quick_xml::{encoding::EncodingError, escape::EscapeError};
2use std::{error, fmt, io};
3
4#[cfg(feature = "serde")]
5use crate::stream::Event;
6use crate::{InvalidXmlDate, Value};
7
8#[derive(Debug)]
10pub struct Error {
11 inner: Box<ErrorImpl>,
12}
13
14#[derive(Debug)]
15pub(crate) struct ErrorImpl {
16 kind: ErrorKind,
17 file_position: Option<FilePosition>,
18}
19
20#[derive(Debug)]
21pub(crate) enum ErrorKind {
22 UnexpectedEof,
23 UnexpectedEndOfEventStream,
24 UnexpectedEventType {
25 #[allow(dead_code)]
27 expected: EventKind,
28 #[allow(dead_code)]
29 found: EventKind,
30 },
31 ExpectedEndOfEventStream {
32 #[allow(dead_code)]
34 found: EventKind,
35 },
36
37 UnclosedString,
39 IncompleteComment,
40 InvalidUtf8AsciiStream,
41 InvalidOctalString,
42
43 UnclosedXmlElement,
45 UnexpectedXmlCharactersExpectedElement,
46 UnexpectedXmlOpeningTag,
47 UnknownXmlElement,
48 InvalidXmlSyntax,
49 InvalidXmlUtf8,
50 InvalidDataString,
51 InvalidDateString,
52 InvalidIntegerString,
53 InvalidRealString,
54 UidNotSupportedInXmlPlist,
55
56 ObjectTooLarge,
58 InvalidMagic,
59 InvalidTrailerObjectOffsetSize, InvalidTrailerObjectReferenceSize, InvalidObjectLength,
62 ObjectReferenceTooLarge,
63 ObjectOffsetTooLarge,
64 RecursiveObject,
65 NullObjectUnimplemented,
66 FillObjectUnimplemented,
67 IntegerOutOfRange,
68 OverflowOrNanDate,
69 InvalidUtf8String,
70 InvalidUtf16String,
71 UnknownObjectType(
72 #[allow(dead_code)] u8,
74 ),
75
76 Io(io::Error),
77 #[cfg(feature = "serde")]
78 Serde(
79 #[allow(dead_code)] String,
81 ),
82}
83
84#[derive(Debug, Clone, Copy)]
85pub(crate) struct FilePosition(pub(crate) u64);
86
87#[derive(Copy, Clone, PartialEq, Eq, Debug)]
88pub(crate) enum EventKind {
89 StartArray,
90 StartDictionary,
91 EndCollection,
92 Boolean,
93 Data,
94 Date,
95 Integer,
96 Real,
97 String,
98 Uid,
99
100 ValueOrStartCollection,
101 DictionaryKeyOrEndCollection,
102}
103
104impl Error {
105 pub fn is_io(&self) -> bool {
107 self.as_io().is_some()
108 }
109
110 pub fn is_eof(&self) -> bool {
112 matches!(self.inner.kind, ErrorKind::UnexpectedEof)
113 }
114
115 pub fn as_io(&self) -> Option<&io::Error> {
118 if let ErrorKind::Io(err) = &self.inner.kind {
119 Some(err)
120 } else {
121 None
122 }
123 }
124
125 pub fn into_io(self) -> Result<io::Error, Self> {
128 if let ErrorKind::Io(err) = self.inner.kind {
129 Ok(err)
130 } else {
131 Err(self)
132 }
133 }
134}
135
136impl error::Error for Error {
137 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
138 match &self.inner.kind {
139 ErrorKind::Io(err) => Some(err),
140 _ => None,
141 }
142 }
143}
144
145impl fmt::Display for Error {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 if let Some(position) = &self.inner.file_position {
148 write!(f, "{:?} ({})", self.inner.kind, position)
149 } else {
150 fmt::Debug::fmt(&self.inner.kind, f)
151 }
152 }
153}
154
155impl fmt::Display for FilePosition {
156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 write!(f, "offset {}", self.0)
158 }
159}
160
161impl From<InvalidXmlDate> for Error {
162 fn from(error: InvalidXmlDate) -> Self {
163 ErrorKind::from(error).without_position()
164 }
165}
166
167impl ErrorKind {
168 pub fn with_byte_offset(self, offset: u64) -> Error {
169 self.with_position(FilePosition(offset))
170 }
171
172 pub fn with_position(self, pos: FilePosition) -> Error {
173 Error {
174 inner: Box::new(ErrorImpl {
175 kind: self,
176 file_position: Some(pos),
177 }),
178 }
179 }
180
181 pub fn without_position(self) -> Error {
182 Error {
183 inner: Box::new(ErrorImpl {
184 kind: self,
185 file_position: None,
186 }),
187 }
188 }
189}
190
191impl From<InvalidXmlDate> for ErrorKind {
192 fn from(_: InvalidXmlDate) -> Self {
193 ErrorKind::InvalidDateString
194 }
195}
196
197impl From<EscapeError> for ErrorKind {
198 fn from(_: EscapeError) -> Self {
199 ErrorKind::InvalidXmlUtf8
200 }
201}
202
203impl From<EncodingError> for ErrorKind {
204 fn from(_: EncodingError) -> Self {
205 ErrorKind::InvalidXmlUtf8
206 }
207}
208
209impl EventKind {
210 #[cfg(feature = "serde")]
211 pub fn of_event(event: &Event) -> EventKind {
212 match event {
213 Event::StartArray(_) => EventKind::StartArray,
214 Event::StartDictionary(_) => EventKind::StartDictionary,
215 Event::EndCollection => EventKind::EndCollection,
216 Event::Boolean(_) => EventKind::Boolean,
217 Event::Data(_) => EventKind::Data,
218 Event::Date(_) => EventKind::Date,
219 Event::Integer(_) => EventKind::Integer,
220 Event::Real(_) => EventKind::Real,
221 Event::String(_) => EventKind::String,
222 Event::Uid(_) => EventKind::Uid,
223 }
224 }
225
226 pub fn of_value(event: &Value) -> EventKind {
227 match event {
228 Value::Array(_) => EventKind::StartArray,
229 Value::Dictionary(_) => EventKind::StartDictionary,
230 Value::Boolean(_) => EventKind::Boolean,
231 Value::Data(_) => EventKind::Data,
232 Value::Date(_) => EventKind::Date,
233 Value::Integer(_) => EventKind::Integer,
234 Value::Real(_) => EventKind::Real,
235 Value::String(_) => EventKind::String,
236 Value::Uid(_) => EventKind::Uid,
237 }
238 }
239}
240
241impl fmt::Display for EventKind {
242 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243 match self {
244 EventKind::StartArray => "StartArray",
245 EventKind::StartDictionary => "StartDictionary",
246 EventKind::EndCollection => "EndCollection",
247 EventKind::Boolean => "Boolean",
248 EventKind::Data => "Data",
249 EventKind::Date => "Date",
250 EventKind::Integer => "Integer",
251 EventKind::Real => "Real",
252 EventKind::String => "String",
253 EventKind::Uid => "Uid",
254 EventKind::ValueOrStartCollection => "value or start collection",
255 EventKind::DictionaryKeyOrEndCollection => "dictionary key or end collection",
256 }
257 .fmt(f)
258 }
259}
260
261pub(crate) fn from_io_without_position(err: io::Error) -> Error {
262 ErrorKind::Io(err).without_position()
263}
264
265#[cfg(feature = "serde")]
266pub(crate) fn unexpected_event_type(expected: EventKind, found: &Event) -> Error {
267 let found = EventKind::of_event(found);
268 ErrorKind::UnexpectedEventType { expected, found }.without_position()
269}