1use alloc::string::String;
2use core::fmt;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct DecodeError {
6 kind: DecodeErrorKind,
7 position: usize,
8}
9
10impl DecodeError {
11 pub fn new(kind: DecodeErrorKind, position: usize) -> Self {
12 Self { kind, position }
13 }
14
15 pub fn kind(&self) -> &DecodeErrorKind {
16 &self.kind
17 }
18
19 pub fn position(&self) -> usize {
20 self.position
21 }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum DecodeErrorKind {
26 UnexpectedEnd,
27 InvalidMajorType(u8),
28 NestingTooDeep,
29 IndefiniteLength,
30 FloatNotAllowed,
31 UnsortedMapKeys,
32 NonCanonicalInteger,
33 DuplicateMapKey,
34 TrailingContent,
35 InvalidUtf8,
36 NonTextMapKey,
37 UnsupportedTag(u64),
38 IntegerOverflow,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub enum AccessError {
43 NotAMap,
44 MissingField(String),
45 TypeMismatch {
46 field: String,
47 expected: &'static str,
48 },
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub enum EncodeError {
53 NonTextKeyInDagMode,
54 DuplicateKeyInDagMode,
55 UnsupportedTag(u64),
56 InvalidTag42Payload,
57 InvalidNegativeValue(i64),
58}
59
60impl fmt::Display for DecodeError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 write!(
63 f,
64 "CBOR decode error at position {}: {}",
65 self.position,
66 self.kind()
67 )
68 }
69}
70
71impl fmt::Display for DecodeErrorKind {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 match self {
74 Self::UnexpectedEnd => f.write_str("unexpected end of input"),
75 Self::InvalidMajorType(major) => write!(f, "invalid major type {major}"),
76 Self::NestingTooDeep => f.write_str("nesting too deep"),
77 Self::IndefiniteLength => f.write_str("indefinite-length item is not supported"),
78 Self::FloatNotAllowed => f.write_str("floating-point values are not supported"),
79 Self::UnsortedMapKeys => f.write_str("map keys are not sorted in DAG-CBOR order"),
80 Self::NonCanonicalInteger => f.write_str("integer is not encoded canonically"),
81 Self::DuplicateMapKey => f.write_str("duplicate map key"),
82 Self::TrailingContent => f.write_str("trailing content after CBOR value"),
83 Self::InvalidUtf8 => f.write_str("invalid UTF-8"),
84 Self::NonTextMapKey => f.write_str("map key must be text in DAG-CBOR mode"),
85 Self::UnsupportedTag(tag) => write!(f, "unsupported tag {tag}"),
86 Self::IntegerOverflow => f.write_str("integer does not fit in target representation"),
87 }
88 }
89}
90
91impl fmt::Display for AccessError {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 match self {
94 Self::NotAMap => f.write_str("value is not a map"),
95 Self::MissingField(field) => write!(f, "missing field \"{field}\""),
96 Self::TypeMismatch { field, expected } => {
97 write!(f, "field \"{field}\": expected {expected}")
98 }
99 }
100 }
101}
102
103impl fmt::Display for EncodeError {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 match self {
106 Self::NonTextKeyInDagMode => f.write_str("map key must be text in DAG-CBOR mode"),
107 Self::DuplicateKeyInDagMode => f.write_str("duplicate map key in DAG-CBOR mode"),
108 Self::UnsupportedTag(tag) => write!(f, "unsupported tag {tag}"),
109 Self::InvalidTag42Payload => {
110 f.write_str("tag 42 payload must be a byte string prefixed with 0x00")
111 }
112 Self::InvalidNegativeValue(value) => {
113 write!(f, "negative integer value must be less than zero: {value}")
114 }
115 }
116 }
117}
118
119impl core::error::Error for DecodeError {}
120impl core::error::Error for AccessError {}
121impl core::error::Error for EncodeError {}