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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import_stdlib!();
use core::str::Utf8Error;
use crate::tag::Tag;
/// A comprehensive set of errors that can occur during CBOR encoding and
/// decoding operations, with special focus on enforcing the deterministic
/// encoding rules specified in the dCBOR specification.
///
/// The dCBOR implementation validates all encoded CBOR against the
/// deterministic encoding requirements of RFC 8949 §4.2.1, plus additional
/// constraints defined in the dCBOR application profile. These errors represent
/// all the possible validation failures and decoding issues that can arise.
///
/// # Examples
///
/// ```
/// use dcbor::prelude::*;
///
/// // Handling the WrongType error when trying to convert a different type
/// let cbor_string = CBOR::from("hello");
/// let result = cbor_string.try_into_byte_string();
///
/// assert!(result.is_err());
/// if let Err(e) = result {
/// assert!(e.to_string().contains("not the expected type"));
/// }
/// ```
#[derive(Debug, ThisError)]
pub enum Error {
/// The CBOR data ended prematurely during decoding, before a complete CBOR
/// item could be decoded. This typically happens when a CBOR item's
/// structure indicates more data than is actually present.
#[error("early end of CBOR data")]
Underrun,
/// An unsupported or invalid value was encountered in a CBOR header byte.
/// The parameter contains the unsupported header byte value.
/// This can occur when decoding CBOR that uses unsupported features or is
/// malformed.
#[error("unsupported value in CBOR header")]
UnsupportedHeaderValue(u8),
/// A CBOR numeric value was encoded in a non-canonical form, violating the
/// deterministic encoding requirement of dCBOR (per Section 2.3 of the
/// dCBOR specification).
///
/// This error is triggered when:
/// - An integer is not encoded in its shortest possible form
/// - A floating point value that could be represented as an integer was not
/// reduced
/// - A NaN value was not encoded in its canonical form (`f97e00`)
#[error("a CBOR numeric value was encoded in non-canonical form")]
NonCanonicalNumeric,
/// An invalid CBOR simple value was encountered during decoding.
///
/// Per Section 2.4 of the dCBOR specification, only `false`, `true`,
/// `null`, and floating point values are valid simple values in dCBOR.
/// All other major type 7 values are invalid.
#[error("an invalid CBOR simple value was encountered")]
InvalidSimpleValue,
/// A CBOR text string was not valid UTF-8. The parameter contains the
/// specific UTF-8 error.
///
/// All CBOR text strings (major type 3) must be valid UTF-8 per RFC 8949.
#[error(
"an invalidly-encoded UTF-8 string was encountered in the CBOR ({0:?})"
)]
InvalidString(str::Utf8Error),
/// A CBOR text string was not encoded in Unicode Canonical Normalization
/// Form C (NFC).
///
/// Per Section 2.5 of the dCBOR specification, all text strings must be in
/// NFC form, and decoders must reject any encoded text strings that are
/// not in NFC.
#[error(
"a CBOR string was not encoded in Unicode Canonical Normalization Form C"
)]
NonCanonicalString,
/// The decoded CBOR item didn't consume all input data.
/// The parameter contains the number of unused bytes.
///
/// This error occurs when decoding functions expect exactly one CBOR item
/// but the input contains additional data after a valid CBOR item.
#[error("the decoded CBOR had {0} extra bytes at the end")]
UnusedData(usize),
/// The keys in a decoded CBOR map were not in canonical lexicographic order
/// of their encoding.
///
/// Per the CDE specification and Section 2.1 of dCBOR, map keys must be in
/// ascending lexicographic order of their encoded representation for
/// deterministic encoding.
#[error("the decoded CBOR map has keys that are not in canonical order")]
MisorderedMapKey,
/// A decoded CBOR map contains duplicate keys, which is invalid.
///
/// Per Section 2.2 of the dCBOR specification, CBOR maps must not contain
/// duplicate keys, and decoders must reject encoded maps with duplicate
/// keys.
#[error("the decoded CBOR map has a duplicate key")]
DuplicateMapKey,
/// A requested key was not found in a CBOR map during data extraction.
#[error("missing CBOR map key")]
MissingMapKey,
/// A CBOR numeric value could not be represented in the specified target
/// numeric type.
///
/// This occurs when attempting to convert a CBOR number to a Rust numeric
/// type that is too small to represent the value without loss of
/// precision.
#[error(
"the CBOR numeric value could not be represented in the specified numeric type"
)]
OutOfRange,
/// The CBOR value is not of the expected type for a conversion or
/// operation.
///
/// This occurs when attempting to convert a CBOR value to a type that
/// doesn't match the actual CBOR item's type (e.g., trying to convert a
/// string to an integer).
#[error("the decoded CBOR value was not the expected type")]
WrongType,
/// The CBOR tagged value had a different tag than expected.
/// The first parameter is the expected tag, and the second is the actual
/// tag found.
#[error("expected CBOR tag {0}, but got {1}")]
WrongTag(Tag, Tag),
/// Invalid UTF‑8 in a text string.
#[error("invalid UTF‑8 string: {0}")]
InvalidUtf8(#[from] Utf8Error),
/// Invalid ISO 8601 date format.
#[error("invalid ISO 8601 date string: {0}")]
InvalidDate(String),
/// Custom error message.
#[error("{0}")]
Custom(String),
}
impl Error {
pub fn msg(s: impl Into<String>) -> Self { Error::Custom(s.into()) }
}
impl From<&str> for Error {
/// Converts a string slice into a `CBORError::Custom` variant.
fn from(error: &str) -> Self { Error::msg(error) }
}
impl From<String> for Error {
/// Converts a `String` into a `CBORError::Custom` variant.
fn from(error: String) -> Self { Error::msg(error) }
}
pub type Result<T> = StdResult<T, Error>;