1use std::{error, fmt, io};
2
3use crate::stream::Event;
4
5#[derive(Debug)]
7pub struct Error {
8 inner: Box<ErrorImpl>,
9}
10
11#[derive(Debug)]
12pub(crate) struct ErrorImpl {
13 kind: ErrorKind,
14 file_position: Option<FilePosition>,
15}
16
17#[derive(Debug)]
18pub(crate) enum ErrorKind {
19 UnexpectedEof,
20 UnexpectedEndOfEventStream,
21 UnexpectedEventType {
22 expected: EventKind,
23 found: EventKind,
24 },
25
26 UnclosedXmlElement,
28 UnpairedXmlClosingTag,
29 UnexpectedXmlCharactersExpectedElement,
30 UnexpectedXmlOpeningTag,
31 UnknownXmlElement,
32 InvalidXmlSyntax,
33 InvalidXmlUtf8,
34 InvalidDataString,
35 InvalidDateString,
36 InvalidIntegerString,
37 InvalidRealString,
38 UidNotSupportedInXmlPlist,
39
40 ObjectTooLarge,
42 InvalidMagic,
43 InvalidTrailerObjectOffsetSize, InvalidTrailerObjectReferenceSize, InvalidObjectLength,
46 ObjectReferenceTooLarge,
47 ObjectOffsetTooLarge,
48 RecursiveObject,
49 NullObjectUnimplemented,
50 FillObjectUnimplemented,
51 IntegerOutOfRange,
52 InfiniteOrNanDate,
53 InvalidUtf8String,
54 InvalidUtf16String,
55 UnknownObjectType(u8),
56
57 Io(io::Error),
58 Serde(String),
59}
60
61#[derive(Debug)]
62pub(crate) enum FilePosition {
63 LineColumn(u64, u64),
64 Offset(u64),
65}
66
67#[derive(Copy, Clone, PartialEq, Eq, Debug)]
68pub(crate) enum EventKind {
69 StartArray,
70 StartDictionary,
71 EndCollection,
72 Boolean,
73 Data,
74 Date,
75 Integer,
76 Real,
77 String,
78 Uid,
79
80 ValueOrStartCollection,
81 DictionaryKeyOrEndCollection,
82}
83
84impl Error {
85 pub fn is_io(&self) -> bool {
87 self.as_io().is_some()
88 }
89
90 pub fn is_eof(&self) -> bool {
92 if let ErrorKind::UnexpectedEof = self.inner.kind {
93 true
94 } else {
95 false
96 }
97 }
98
99 pub fn as_io(&self) -> Option<&io::Error> {
102 if let ErrorKind::Io(err) = &self.inner.kind {
103 Some(err)
104 } else {
105 None
106 }
107 }
108
109 pub fn into_io(self) -> Result<io::Error, Self> {
112 if let ErrorKind::Io(err) = self.inner.kind {
113 Ok(err)
114 } else {
115 Err(self)
116 }
117 }
118}
119
120impl error::Error for Error {
121 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
122 match &self.inner.kind {
123 ErrorKind::Io(err) => Some(err),
124 _ => None,
125 }
126 }
127}
128
129impl fmt::Display for Error {
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 fmt::Debug::fmt(&self.inner.kind, f)
132 }
133}
134
135impl ErrorKind {
136 pub fn with_byte_offset(self, offset: u64) -> Error {
137 self.with_position(FilePosition::Offset(offset))
138 }
139
140 pub fn with_position(self, pos: FilePosition) -> Error {
141 Error {
142 inner: Box::new(ErrorImpl {
143 kind: self,
144 file_position: Some(pos),
145 }),
146 }
147 }
148
149 pub fn without_position(self) -> Error {
150 Error {
151 inner: Box::new(ErrorImpl {
152 kind: self,
153 file_position: None,
154 }),
155 }
156 }
157}
158
159impl EventKind {
160 pub fn of_event(event: &Event) -> EventKind {
161 match event {
162 Event::StartArray(_) => EventKind::StartArray,
163 Event::StartDictionary(_) => EventKind::StartDictionary,
164 Event::EndCollection => EventKind::EndCollection,
165 Event::Boolean(_) => EventKind::Boolean,
166 Event::Data(_) => EventKind::Data,
167 Event::Date(_) => EventKind::Date,
168 Event::Integer(_) => EventKind::Integer,
169 Event::Real(_) => EventKind::Real,
170 Event::String(_) => EventKind::String,
171 Event::Uid(_) => EventKind::Uid,
172 Event::__Nonexhaustive => unreachable!(),
173 }
174 }
175}
176
177impl fmt::Display for EventKind {
178 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179 match self {
180 EventKind::StartArray => "StartArray",
181 EventKind::StartDictionary => "StartDictionary",
182 EventKind::EndCollection => "EndCollection",
183 EventKind::Boolean => "Boolean",
184 EventKind::Data => "Data",
185 EventKind::Date => "Date",
186 EventKind::Integer => "Integer",
187 EventKind::Real => "Real",
188 EventKind::String => "String",
189 EventKind::Uid => "Uid",
190 EventKind::ValueOrStartCollection => "value or start collection",
191 EventKind::DictionaryKeyOrEndCollection => "dictionary key or end collection",
192 }
193 .fmt(f)
194 }
195}
196
197pub(crate) fn from_io_without_position(err: io::Error) -> Error {
198 ErrorKind::Io(err).without_position()
199}
200
201pub(crate) fn unexpected_event_type(expected: EventKind, found: &Event) -> Error {
202 let found = EventKind::of_event(&found);
203 ErrorKind::UnexpectedEventType { expected, found }.without_position()
204}