1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use core::fmt;
/// The result type returned by this crate.
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
/// The category of a CBOR encoding or decoding error.
pub enum ErrorKind {
/// The input ended before the current item was complete.
Eof,
/// An initial byte contained reserved or invalid additional information.
InvalidAdditionalInfo,
/// The encountered CBOR type did not match the requested type.
UnexpectedType,
/// A break code appeared outside its permitted position.
UnexpectedBreak,
/// A text string was not valid UTF-8.
InvalidUtf8,
/// An integer cannot be represented by the requested Rust type.
IntegerOverflow,
/// The configured nesting-depth limit was exceeded.
DepthLimit,
/// The configured collection-length limit was exceeded.
CollectionLimit,
/// Bytes remain after the expected item.
TrailingData,
/// Input violated deterministic CBOR encoding requirements.
NonDeterministic,
/// A deterministic map contained duplicate encoded keys.
DuplicateKey,
/// The provided output buffer lacks sufficient capacity.
OutputTooSmall,
/// An underlying reader or writer reported an I/O error.
#[cfg(feature = "std")]
Io,
/// An underlying serializer reported an opaque error.
Message,
}
#[cfg_attr(not(feature = "std"), derive(Clone, Copy, Eq, PartialEq))]
#[derive(Debug)]
/// An error with its category and byte offset.
pub struct Error {
kind: ErrorKind,
offset: usize,
item: Option<usize>,
#[cfg(feature = "std")]
io: Option<std::io::Error>,
}
impl Error {
/// Creates an error of `kind` at the given byte `offset`.
pub const fn new(kind: ErrorKind, offset: usize) -> Self {
Self {
kind,
offset,
item: None,
#[cfg(feature = "std")]
io: None,
}
}
/// Returns this error's category.
pub const fn kind(&self) -> ErrorKind {
self.kind
}
/// Returns the byte offset at which the error was detected.
pub const fn offset(&self) -> usize {
self.offset
}
/// Returns the zero-based sequence item index, when available.
pub const fn item_index(&self) -> Option<usize> {
self.item
}
/// Returns the underlying I/O error, when this error came from a reader or writer.
#[cfg(feature = "std")]
pub fn io_error(&self) -> Option<&std::io::Error> {
self.io.as_ref()
}
#[cfg(feature = "std")]
pub(crate) fn from_io(error: std::io::Error, offset: usize) -> Self {
Self {
kind: ErrorKind::Io,
offset,
item: None,
io: Some(error),
}
}
pub(crate) const fn with_item(mut self, item: usize) -> Self {
self.item = Some(item);
self
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(feature = "std")]
if let Some(error) = &self.io {
write!(f, "I/O error at byte {}: {error}", self.offset)?;
} else {
write!(f, "{:?} at byte {}", self.kind, self.offset)?;
}
#[cfg(not(feature = "std"))]
write!(f, "{:?} at byte {}", self.kind, self.offset)?;
if let Some(item) = self.item {
write!(f, " (sequence item {item})")?;
}
Ok(())
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.io
.as_ref()
.map(|error| error as &(dyn std::error::Error + 'static))
}
}