cardano_message_signing/
error.rs

1#[derive(Debug)]
2pub enum Key {
3    Str(String),
4    Uint(u64),
5    Nint(u64),
6}
7
8impl std::fmt::Display for Key {
9    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10        match self {
11            Key::Str(x) => write!(f, "\"{}\"", x),
12            Key::Uint(x) => write!(f, "{}", x),
13            Key::Nint(x) => write!(f, "-{}", x),
14        }
15    }
16}
17
18#[derive(Debug)]
19pub enum DeserializeFailure {
20    BreakInDefiniteLen,
21    CBOR(cbor_event::Error),
22    DefiniteLenMismatch(u64, Option<u64>),
23    DuplicateKey(Key),
24    EndingBreakMissing,
25    ExpectedNull,
26    FixedValueMismatch{
27        found: Key,
28        expected: Key,
29    },
30    MandatoryFieldMissing(Key),
31    NoVariantMatched,
32    TagMismatch{
33        found: u64,
34        expected: u64,
35    },
36    UnknownKey(Key),
37    UnexpectedKeyType(cbor_event::Type),
38}
39
40// we might want to add more info like which field,
41#[derive(Debug)]
42pub struct DeserializeError {
43    pub location: Option<String>,
44    pub failure: DeserializeFailure,
45}
46
47impl DeserializeError {
48    pub fn new<T: Into<String>>(location: T, failure: DeserializeFailure) -> Self {
49        Self {
50            location: Some(location.into()),
51            failure,
52        }
53    }
54
55    pub fn annotate<T: Into<String>>(self, location: T) -> Self {
56        match self.location {
57            Some(loc) => Self::new(format!("{}.{}", location.into(), loc), self.failure),
58            None => Self::new(location, self.failure),
59        }
60    }
61}
62
63impl std::fmt::Display for DeserializeError {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        match &self.location {
66            Some(loc) => write!(f, "Deserialization failed in {} because: ", loc),
67            None => write!(f, "Deserialization: "),
68        }?;
69        match &self.failure {
70            DeserializeFailure::BreakInDefiniteLen => write!(f, "Encountered CBOR Break while reading definite length sequence"),
71            DeserializeFailure::CBOR(e) => e.fmt(f),
72            DeserializeFailure::DefiniteLenMismatch(found, expected) => {
73                write!(f, "Definite length mismatch: found {}", found)?;
74                if let Some(expected_elems) = expected {
75                    write!(f, ", expected: {}", expected_elems)?;
76                }
77                Ok(())
78            },
79            DeserializeFailure::DuplicateKey(key) => write!(f, "Duplicate key: {}", key),
80            DeserializeFailure::EndingBreakMissing => write!(f, "Missing ending CBOR Break"),
81            DeserializeFailure::ExpectedNull => write!(f, "Expected null, found other type"),
82            DeserializeFailure::FixedValueMismatch{ found, expected } => write!(f, "Expected fixed value {} found {}", expected, found),
83            DeserializeFailure::MandatoryFieldMissing(key) => write!(f, "Mandatory field {} not found", key),
84            DeserializeFailure::NoVariantMatched => write!(f, "No variant matched"),
85            DeserializeFailure::TagMismatch{ found, expected } => write!(f, "Expected tag {}, found {}", expected, found),
86            DeserializeFailure::UnknownKey(key) => write!(f, "Found unexpected key {}", key),
87            DeserializeFailure::UnexpectedKeyType(ty) => write!(f, "Found unexpected key of CBOR type {:?}", ty),
88        }
89    }
90}
91
92impl From<DeserializeError> for JsError {
93    fn from(e: DeserializeError) -> JsError {
94        JsError::from_str(&e.to_string())
95    }
96}
97
98impl From<DeserializeFailure> for DeserializeError {
99    fn from(failure: DeserializeFailure) -> DeserializeError {
100        DeserializeError {
101            location: None,
102            failure,
103        }
104    }
105}
106
107impl From<cbor_event::Error> for DeserializeError {
108    fn from(err: cbor_event::Error) -> DeserializeError {
109        DeserializeError {
110            location: None,
111            failure: DeserializeFailure::CBOR(err),
112        }
113    }
114}
115
116// Generic string error that is replaced with JsError on wasm builds but still usable from non-wasm builds
117// since JsError panics when used for non-constants in non-wasm builds even just creating one
118
119#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
120pub type JsError = wasm_bindgen::JsValue;
121
122#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
123#[derive(Debug, Clone)]
124pub struct JsError {
125    msg: String,
126}
127
128#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
129impl JsError {
130    pub fn from_str(s: &str) -> Self {
131        Self {
132            msg: s.to_owned(),
133        }
134    }
135
136    // to match JsValue's API even though to_string() exists
137    pub fn as_string(&self) -> Option<String> {
138        Some(self.msg.clone())
139    }
140}
141
142#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
143impl std::fmt::Display for JsError {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        write!(f, "{}", self.msg)
146    }
147}