1use alloc::boxed::Box;
4use alloc::string::ToString;
5use core::fmt::{self, Debug, Display};
6use core::result;
7
8pub type Result<T> = result::Result<T, Error>;
10
11#[derive(Debug)]
13pub struct Expectation<U, E = U> {
14 pub unexpected: U,
16 pub expected: E,
18}
19
20pub struct Error {
22 kind: Box<ErrorKind>,
23 pos: Option<usize>,
24}
25
26impl Error {
27 #[cold]
28 pub(crate) fn new(kind: Box<ErrorKind>, pos: Option<usize>) -> Self {
29 Self { kind, pos }
30 }
31
32 #[cold]
34 pub fn end_of_file() -> Self {
35 Self::new(Box::new(ErrorKind::end_of_file()), None)
36 }
37
38 #[cold]
40 pub fn invalid_type(unexpected: String, expected: String, pos: Option<usize>) -> Self {
41 Self::new(Box::new(ErrorKind::invalid_type(unexpected, expected)), pos)
42 }
43
44 #[cold]
47 pub fn invalid_value(unexpected: String, expected: String, pos: Option<usize>) -> Self {
48 Self::new(
49 Box::new(ErrorKind::invalid_value(unexpected, expected)),
50 pos,
51 )
52 }
53
54 #[cold]
56 pub fn invalid_length(unexpected: String, expected: String, pos: Option<usize>) -> Self {
57 Self::new(
58 Box::new(ErrorKind::invalid_length(unexpected, expected)),
59 pos,
60 )
61 }
62
63 #[cold]
65 pub fn unknown_length() -> Self {
66 Self::new(Box::new(ErrorKind::unknown_length()), None)
67 }
68
69 #[cold]
71 pub fn number_out_of_range(pos: Option<usize>) -> Self {
72 Self::new(Box::new(ErrorKind::number_out_of_range()), pos)
73 }
74
75 #[cold]
77 pub fn uncategorized(msg: impl Display, pos: Option<usize>) -> Self {
78 Self::new(Box::new(ErrorKind::uncategorized(msg)), pos)
79 }
80
81 #[cold]
83 pub fn depth_limit_exceeded(pos: Option<usize>) -> Self {
84 Self::new(Box::new(ErrorKind::depth_limit_exceeded()), pos)
85 }
86
87 #[cold]
89 pub fn utf8(err: core::str::Utf8Error, pos: Option<usize>) -> Self {
90 Self::new(Box::new(ErrorKind::utf8(err)), pos)
91 }
92
93 #[cold]
95 pub fn reserved_type() -> Self {
96 Self::new(Box::new(ErrorKind::reserved_type()), None)
97 }
98
99 #[cfg(feature = "std")]
101 pub fn io(err: std::io::Error) -> Self {
102 Self::new(Box::new(ErrorKind::io(err)), None)
103 }
104
105 pub fn kind(&self) -> &ErrorKind {
107 &self.kind
108 }
109
110 pub fn pos(&self) -> Option<usize> {
112 self.pos
113 }
114
115 pub fn code(&self) -> ErrorCode {
117 self.kind.as_code()
118 }
119}
120
121impl Debug for Error {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123 if let Some(pos) = self.pos {
125 write!(f, "Error({:?}, position: {pos:?})", self.kind.to_string())
126 } else {
127 write!(f, "Error({:?})", self.kind.to_string())
128 }
129 }
130}
131
132impl Display for Error {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 if let Some(pos) = self.pos {
136 write!(f, "{:?}, at position: {pos:?}", self.kind.to_string())
137 } else {
138 write!(f, "{:?}", self.kind.to_string(),)
139 }
140 }
141}
142
143impl std::error::Error for Error {
144 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
145 match &*self.kind {
146 ErrorKind::UnexpectedEndOfFile => None,
147 ErrorKind::InvalidType(_) => None,
148 ErrorKind::InvalidValue(_) => None,
149 ErrorKind::InvalidLength(_) => None,
150 ErrorKind::UnknownLength => None,
151 ErrorKind::NumberOutOfRange => None,
152 ErrorKind::Uncategorized(_) => None,
153 ErrorKind::DepthLimitExceeded => None,
154 ErrorKind::Utf8(err) => Some(err),
155 ErrorKind::ReservedType => None,
156 #[cfg(feature = "std")]
157 ErrorKind::StdIo(err) => Some(err),
158 }
159 }
160}
161
162#[cfg(feature = "serde")]
163impl serde::de::Error for Error {
164 #[cold]
165 fn custom<T>(msg: T) -> Error
166 where
167 T: Display,
168 {
169 Error::uncategorized(msg, None)
170 }
171
172 #[cold]
173 fn invalid_type(unexp: serde::de::Unexpected, exp: &dyn serde::de::Expected) -> Self {
174 Error::invalid_type(unexp.to_string(), exp.to_string(), None)
175 }
176
177 #[cold]
178 fn invalid_value(unexp: serde::de::Unexpected, exp: &dyn serde::de::Expected) -> Self {
179 Error::invalid_value(unexp.to_string(), exp.to_string(), None)
180 }
181
182 #[cold]
183 fn invalid_length(len: usize, exp: &dyn serde::de::Expected) -> Self {
184 Error::invalid_length(len.to_string(), exp.to_string(), None)
185 }
186}
187
188#[cfg(feature = "serde")]
189impl serde::ser::Error for Error {
190 fn custom<T>(msg: T) -> Self
191 where
192 T: Display,
193 {
194 Error::uncategorized(msg, None)
195 }
196}
197
198#[repr(u8)]
201#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
202pub enum ErrorCode {
203 UnexpectedEndOfFile = 1,
205 InvalidType = 11,
207 InvalidValue = 21,
210 InvalidLength = 31,
212 UnknownLength = 41,
214 NumberOutOfRange = 51,
216 Uncategorized = 61,
218 DepthLimitExceeded = 71,
220 Utf8 = 81,
222 ReservedType = 91,
224 #[cfg(feature = "std")]
226 StdIo = 255,
227}
228
229#[derive(Debug)]
232pub enum ErrorKind {
233 UnexpectedEndOfFile,
235 InvalidType(Expectation<String>),
237 InvalidValue(Expectation<String>),
240 InvalidLength(Expectation<String>),
242 UnknownLength,
244 NumberOutOfRange,
246 Uncategorized(String),
248 DepthLimitExceeded,
250 Utf8(core::str::Utf8Error),
252 ReservedType,
254 #[cfg(feature = "std")]
256 StdIo(std::io::Error),
257}
258
259impl ErrorKind {
260 fn end_of_file() -> Self {
262 Self::UnexpectedEndOfFile
263 }
264
265 fn invalid_type(unexpected: String, expected: String) -> Self {
267 Self::InvalidType(Expectation {
268 unexpected,
269 expected,
270 })
271 }
272
273 fn invalid_value(unexpected: String, expected: String) -> Self {
276 Self::InvalidValue(Expectation {
277 unexpected,
278 expected,
279 })
280 }
281
282 fn invalid_length(unexpected: String, expected: String) -> Self {
284 Self::InvalidLength(Expectation {
285 unexpected,
286 expected,
287 })
288 }
289
290 #[cold]
292 pub fn unknown_length() -> Self {
293 Self::UnknownLength
294 }
295
296 fn number_out_of_range() -> Self {
298 Self::NumberOutOfRange
299 }
300
301 fn uncategorized(msg: impl Display) -> Self {
303 Self::Uncategorized(msg.to_string())
304 }
305
306 fn depth_limit_exceeded() -> Self {
308 Self::DepthLimitExceeded
309 }
310
311 fn utf8(err: core::str::Utf8Error) -> Self {
313 Self::Utf8(err)
314 }
315
316 fn reserved_type() -> Self {
318 Self::ReservedType
319 }
320
321 #[cfg(feature = "std")]
322 fn io(err: std::io::Error) -> Self {
323 if err.kind() == std::io::ErrorKind::UnexpectedEof {
324 return Self::UnexpectedEndOfFile;
325 }
326
327 Self::StdIo(err)
328 }
329
330 pub fn as_code(&self) -> ErrorCode {
332 match self {
333 ErrorKind::UnexpectedEndOfFile => ErrorCode::UnexpectedEndOfFile,
334 ErrorKind::InvalidType(_) => ErrorCode::InvalidType,
335 ErrorKind::InvalidValue(_) => ErrorCode::InvalidValue,
336 ErrorKind::InvalidLength(_) => ErrorCode::InvalidLength,
337 ErrorKind::UnknownLength => ErrorCode::UnknownLength,
338 ErrorKind::NumberOutOfRange => ErrorCode::NumberOutOfRange,
339 ErrorKind::Uncategorized(_) => ErrorCode::Uncategorized,
340 ErrorKind::DepthLimitExceeded => ErrorCode::DepthLimitExceeded,
341 ErrorKind::Utf8(_) => ErrorCode::Utf8,
342 ErrorKind::ReservedType => ErrorCode::ReservedType,
343 ErrorKind::StdIo(_) => ErrorCode::StdIo,
344 }
345 }
346}
347
348impl Display for ErrorKind {
349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350 match self {
351 Self::UnexpectedEndOfFile => f.write_str("unexpected EOF while parsing"),
352 Self::InvalidType(unexpected) => {
353 write!(
354 f,
355 "expected type {}, found type {}",
356 unexpected.expected, unexpected.unexpected
357 )
358 }
359 Self::InvalidValue(unexpected) => {
360 write!(
361 f,
362 "expected data {}, found type {}",
363 unexpected.expected, unexpected.unexpected
364 )
365 }
366 Self::InvalidLength(unexpected) => {
367 write!(
368 f,
369 "expected length {}, found length {}",
370 unexpected.expected, unexpected.unexpected
371 )
372 }
373 Self::UnknownLength => f.write_str("unknown length"),
374 Self::NumberOutOfRange => f.write_str("unexpected EOF while parsing"),
375 Self::Uncategorized(msg) => f.write_str(msg),
376 Self::DepthLimitExceeded => {
377 f.write_str("a numeric cast failed due to an out-of-range error")
378 }
379 Self::Utf8(err) => Display::fmt(err, f),
380 Self::ReservedType => f.write_str("reserved type"),
381 #[cfg(feature = "std")]
382 Self::StdIo(err) => Display::fmt(err, f),
383 }
384 }
385}