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