cml_core/
error.rs

1#[derive(Debug)]
2pub enum Key {
3    Str(String),
4    Uint(u64),
5}
6
7impl std::fmt::Display for Key {
8    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9        match self {
10            Key::Str(x) => write!(f, "\"{x}\""),
11            Key::Uint(x) => write!(f, "{x}"),
12        }
13    }
14}
15
16#[derive(Debug)]
17pub enum DeserializeFailure {
18    BadAddressType(u8),
19    BreakInDefiniteLen,
20    CBOR(cbor_event::Error),
21    DefiniteLenMismatch(u64, Option<u64>),
22    DuplicateKey(Key),
23    EndingBreakMissing,
24    ExpectedNull,
25    FixedValueMismatch {
26        found: Key,
27        expected: Key,
28    },
29    /// Invalid internal structure imposed on top of the CBOR format
30    InvalidStructure(Box<dyn std::error::Error>),
31    MandatoryFieldMissing(Key),
32    NoVariantMatched,
33    NoVariantMatchedWithCauses(Vec<DeserializeError>),
34    OutOfRange {
35        min: usize,
36        max: usize,
37        found: usize,
38    },
39    RangeCheck {
40        found: isize,
41        min: Option<isize>,
42        max: Option<isize>,
43    },
44    TagMismatch {
45        found: u64,
46        expected: u64,
47    },
48    UnknownKey(Key),
49    UnexpectedKeyType(cbor_event::Type),
50    VariableLenNatDecodeFailed,
51}
52
53// we might want to add more info like which field,
54#[derive(Debug)]
55pub struct DeserializeError {
56    location: Option<String>,
57    failure: DeserializeFailure,
58}
59
60impl DeserializeError {
61    pub fn new<T: Into<String>>(location: T, failure: DeserializeFailure) -> Self {
62        Self {
63            location: Some(location.into()),
64            failure,
65        }
66    }
67
68    pub fn annotate<T: Into<String>>(self, location: T) -> Self {
69        match self.location {
70            Some(loc) => Self::new(format!("{}.{}", location.into(), loc), self.failure),
71            None => Self::new(location, self.failure),
72        }
73    }
74
75    fn fmt_indent(&self, f: &mut std::fmt::Formatter<'_>, indent: u32) -> std::fmt::Result {
76        use std::fmt::Display;
77        for _ in 0..indent {
78            write!(f, "\t")?;
79        }
80        match &self.location {
81            Some(loc) => write!(f, "Deserialization failed in {loc} because: "),
82            None => write!(f, "Deserialization: "),
83        }?;
84        match &self.failure {
85            DeserializeFailure::BadAddressType(header) => {
86                write!(f, "Encountered unknown address header {header:#08b}")
87            }
88            DeserializeFailure::BreakInDefiniteLen => write!(
89                f,
90                "Encountered CBOR Break while reading definite length sequence"
91            ),
92            DeserializeFailure::CBOR(e) => e.fmt(f),
93            DeserializeFailure::DefiniteLenMismatch(found, expected) => {
94                write!(f, "Definite length mismatch: found {found}")?;
95                if let Some(expected_elems) = expected {
96                    write!(f, ", expected: {expected_elems}")?;
97                }
98                Ok(())
99            }
100            DeserializeFailure::DuplicateKey(key) => write!(f, "Duplicate key: {key}"),
101            DeserializeFailure::EndingBreakMissing => write!(f, "Missing ending CBOR Break"),
102            DeserializeFailure::ExpectedNull => write!(f, "Expected null, found other type"),
103            DeserializeFailure::FixedValueMismatch { found, expected } => {
104                write!(f, "Expected fixed value {expected} found {found}")
105            }
106            DeserializeFailure::InvalidStructure(e) => {
107                write!(f, "Invalid internal structure: {e}")
108            }
109            DeserializeFailure::MandatoryFieldMissing(key) => {
110                write!(f, "Mandatory field {key} not found")
111            }
112            DeserializeFailure::NoVariantMatched => write!(f, "No variant matched"),
113            DeserializeFailure::NoVariantMatchedWithCauses(errs) => {
114                writeln!(f, "No variant matched. Failures:")?;
115                for e in errs {
116                    e.fmt_indent(f, indent + 1)?;
117                    writeln!(f)?;
118                }
119                Ok(())
120            }
121            DeserializeFailure::OutOfRange { min, max, found } => {
122                write!(f, "Out of range: {found} - must be in range {min} - {max}")
123            }
124            DeserializeFailure::RangeCheck { found, min, max } => match (min, max) {
125                (Some(min), Some(max)) => write!(f, "{found} not in range {min} - {max}"),
126                (Some(min), None) => write!(f, "{found} not at least {min}"),
127                (None, Some(max)) => write!(f, "{found} not at most {max}"),
128                (None, None) => write!(f, "invalid range (no min nor max specified)"),
129            },
130            DeserializeFailure::TagMismatch { found, expected } => {
131                write!(f, "Expected tag {expected}, found {found}")
132            }
133            DeserializeFailure::UnknownKey(key) => write!(f, "Found unexpected key {key}"),
134            DeserializeFailure::UnexpectedKeyType(ty) => {
135                write!(f, "Found unexpected key of CBOR type {ty:?}")
136            }
137            DeserializeFailure::VariableLenNatDecodeFailed => {
138                write!(f, "Variable length natural number decode failed")
139            }
140        }
141    }
142}
143
144impl std::error::Error for DeserializeError {}
145
146impl std::fmt::Display for DeserializeError {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        self.fmt_indent(f, 0)
149    }
150}
151
152impl From<DeserializeFailure> for DeserializeError {
153    fn from(failure: DeserializeFailure) -> DeserializeError {
154        DeserializeError {
155            location: None,
156            failure,
157        }
158    }
159}
160
161impl From<cbor_event::Error> for DeserializeError {
162    fn from(err: cbor_event::Error) -> DeserializeError {
163        DeserializeError {
164            location: None,
165            failure: DeserializeFailure::CBOR(err),
166        }
167    }
168}
169
170#[derive(Debug, thiserror::Error)]
171pub enum ArithmeticError {
172    #[error("Integer overflow")]
173    IntegerOverflow,
174    #[error("Integer underflow")]
175    IntegerUnderflow,
176}