cardano_serialization_lib/
error.rs

1use std::string::ToString;
2use super::*;
3use crate::chain_crypto;
4use cbor_event::{self};
5
6// This file was code-generated using an experimental CDDL to rust tool:
7// https://github.com/Emurgo/cddl-codegen
8
9#[derive(Debug)]
10pub enum Key {
11    Str(String),
12    Uint(u64),
13    OptUint(Option<u64>),
14}
15
16impl std::fmt::Display for Key {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        match self {
19            Key::Str(x) => write!(f, "\"{}\"", x),
20            Key::Uint(x) => write!(f, "{}", x),
21            Key::OptUint(Some(x)) => write!(f, "{}", x),
22            Key::OptUint(None) => write!(f, "null"),
23        }
24    }
25}
26
27#[derive(Debug)]
28pub enum DeserializeFailure {
29    BadAddressType(u8),
30    BreakInDefiniteLen,
31    CBOR(cbor_event::Error),
32    DefiniteLenMismatch(u64, Option<u64>),
33    DuplicateKey(Key),
34    EndingBreakMissing,
35    ExpectedNull,
36    ExpectedBool,
37    FixedValueMismatch {
38        found: Key,
39        expected: Key,
40    },
41    FixedValuesMismatch {
42        found: Key,
43        expected: Vec<Key>,
44    },
45    MandatoryFieldMissing(Key),
46    Metadata(JsError),
47    NoVariantMatched,
48    OutOfRange {
49        min: usize,
50        max: usize,
51        found: usize,
52    },
53    PublicKeyError(chain_crypto::PublicKeyError),
54    SignatureError(chain_crypto::SignatureError),
55    TagMismatch {
56        found: u64,
57        expected: u64,
58    },
59    UnknownKey(Key),
60    UnexpectedKeyType(cbor_event::Type),
61    VariableLenNatDecodeFailed,
62    IoError(String),
63    ExpectedType(String, cbor_event::Type),
64    CustomError(String),
65}
66
67#[derive(Debug)]
68pub struct DeserializeError {
69    location: Option<String>,
70    failure: DeserializeFailure,
71}
72
73impl DeserializeError {
74    pub fn new<T: Into<String>>(location: T, failure: DeserializeFailure) -> Self {
75        Self {
76            location: Some(location.into()),
77            failure,
78        }
79    }
80
81    pub fn annotate<T: Into<String>>(self, location: T) -> Self {
82        match self.location {
83            Some(loc) => Self::new(format!("{}.{}", location.into(), loc), self.failure),
84            None => Self::new(location, self.failure),
85        }
86    }
87}
88
89impl std::fmt::Display for DeserializeError {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        match &self.location {
92            Some(loc) => write!(f, "Deserialization failed in {} because: ", loc),
93            None => write!(f, "Deserialization: "),
94        }?;
95        match &self.failure {
96            DeserializeFailure::BadAddressType(header) => {
97                write!(f, "Encountered unknown address header {:#08b}", header)
98            }
99            DeserializeFailure::BreakInDefiniteLen => write!(
100                f,
101                "Encountered CBOR Break while reading definite length sequence"
102            ),
103            DeserializeFailure::CBOR(e) => e.fmt(f),
104            DeserializeFailure::DefiniteLenMismatch(found, expected) => {
105                write!(f, "Definite length mismatch: found {}", found)?;
106                if let Some(expected_elems) = expected {
107                    write!(f, ", expected: {}", expected_elems)?;
108                }
109                Ok(())
110            }
111            DeserializeFailure::DuplicateKey(key) => write!(f, "Duplicate key: {}", key),
112            DeserializeFailure::EndingBreakMissing => write!(f, "Missing ending CBOR Break"),
113            DeserializeFailure::ExpectedNull => write!(f, "Expected null, found other type"),
114            DeserializeFailure::ExpectedBool => write!(f, "Expected bool, found other type"),
115            DeserializeFailure::FixedValueMismatch { found, expected } => {
116                write!(f, "Expected fixed value {} found {}", expected, found)
117            }
118            DeserializeFailure::FixedValuesMismatch { found, expected } => {
119                write!(f, "Expected fixed value {:?} found {}", expected, found)
120            }
121            DeserializeFailure::MandatoryFieldMissing(key) => {
122                write!(f, "Mandatory field {} not found", key)
123            }
124            DeserializeFailure::Metadata(e) => write!(f, "Metadata error: {:?}", e),
125            DeserializeFailure::NoVariantMatched => write!(f, "No variant matched"),
126            DeserializeFailure::OutOfRange { min, max, found } => write!(
127                f,
128                "Out of range: {} - must be in range {} - {}",
129                found, min, max
130            ),
131            DeserializeFailure::PublicKeyError(e) => write!(f, "PublicKeyError error: {}", e),
132            DeserializeFailure::SignatureError(e) => write!(f, "Signature error: {}", e),
133            DeserializeFailure::TagMismatch { found, expected } => {
134                write!(f, "Expected tag {}, found {}", expected, found)
135            }
136            DeserializeFailure::UnknownKey(key) => write!(f, "Found unexpected key {}", key),
137            DeserializeFailure::UnexpectedKeyType(ty) => {
138                write!(f, "Found unexpected key of CBOR type {:?}", ty)
139            }
140            DeserializeFailure::VariableLenNatDecodeFailed => {
141                write!(f, "Variable length natural number decode failed")
142            }
143            DeserializeFailure::IoError(e) => write!(f, "IO error: {}", e),
144            DeserializeFailure::CustomError(e) => write!(f, "Deserialize error: {}", e),
145            DeserializeFailure::ExpectedType(expected, found) => {
146                write!(f, "Expected type {}, found {:?}", expected, found)
147            }
148        }
149    }
150}
151
152#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
153impl std::error::Error for DeserializeError {}
154
155impl From<DeserializeError> for JsError {
156    fn from(e: DeserializeError) -> JsError {
157        JsError::from_str(&e.to_string())
158    }
159}
160
161impl From<DeserializeFailure> for DeserializeError {
162    fn from(failure: DeserializeFailure) -> DeserializeError {
163        DeserializeError {
164            location: None,
165            failure,
166        }
167    }
168}
169
170impl From<cbor_event::Error> for DeserializeError {
171    fn from(err: cbor_event::Error) -> DeserializeError {
172        DeserializeError {
173            location: None,
174            failure: DeserializeFailure::CBOR(err),
175        }
176    }
177}
178
179impl From<chain_crypto::SignatureError> for DeserializeError {
180    fn from(err: chain_crypto::SignatureError) -> DeserializeError {
181        DeserializeError {
182            location: None,
183            failure: DeserializeFailure::SignatureError(err),
184        }
185    }
186}
187
188impl From<chain_crypto::PublicKeyError> for DeserializeError {
189    fn from(err: chain_crypto::PublicKeyError) -> DeserializeError {
190        DeserializeError {
191            location: None,
192            failure: DeserializeFailure::PublicKeyError(err),
193        }
194    }
195}
196
197// Generic string error that is replaced with JsError on wasm builds but still usable from non-wasm builds
198// since JsError panics when used for non-constants in non-wasm builds even just creating one
199
200#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
201pub type JsError = JsValue;
202
203#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
204#[derive(Debug, Clone)]
205pub struct JsError {
206    msg: String,
207}
208
209#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
210impl JsError {
211    pub fn from_str(s: &str) -> Self {
212        Self { msg: s.to_owned() }
213    }
214
215    // to match JsValue's API even though to_string() exists
216    pub fn as_string(&self) -> Option<String> {
217        Some(self.msg.clone())
218    }
219}
220
221#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
222impl std::fmt::Display for JsError {
223    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224        write!(f, "{}", self.msg)
225    }
226}
227
228#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
229impl std::error::Error for JsError {}
230
231pub(crate) enum BuilderError {
232    RegularInputIsScript,
233    RegularInputIsFromRewardAddress,
234    MalformedAddress,
235    ScriptAddressTypeMismatch,
236    RegularAddressTypeMismatch,
237    ScriptAddressCredentialMismatch,
238    MintBuilderDifferentScriptType,
239    MintBuilderDifferentRedeemerDataAndExUnits(String, String),
240    MintBuilderDifferentWitnessTypeRef,
241    MintBuilderDifferentWitnessTypeNonRef
242}
243
244impl BuilderError {
245    pub(crate) fn as_str(&self) -> String {
246        match self {
247            BuilderError::RegularInputIsScript => "You can't add a script input to this function. You can use `.add_native_script_utxo` or `.add_plutus_script_utxo` or `.add_native_script_input` or `.add_plutus_script_input` directly to register the input along with the witness.".to_string(),
248            BuilderError::RegularInputIsFromRewardAddress => "You can't use an input from reward address. To spend funds from reward address you to use withdrawal mechanism.".to_string(),
249            BuilderError::MalformedAddress => "The address is malformed.".to_string(),
250            BuilderError::MintBuilderDifferentScriptType => "You can't add a mint to the same policy id but with different script type.".to_string(),
251            BuilderError::MintBuilderDifferentRedeemerDataAndExUnits(redeemer1, redeemer2) => format!("You can't add a mint to the same policy id but with different redeemer data and ex units. Current redeemer  {redeemer1}, your redeemer {redeemer2}"),
252            BuilderError::MintBuilderDifferentWitnessTypeRef => "You can't add a mint to the same policy id but with different witness type. Current witness is ref input".to_string(),
253            BuilderError::MintBuilderDifferentWitnessTypeNonRef => "You can't add a mint to the same policy id but with different witness type. Current witness is non ref".to_string(),
254            BuilderError::ScriptAddressTypeMismatch => "The address should be Base or Pointer or Enterprise.".to_string(),
255            BuilderError::RegularAddressTypeMismatch => "The address should be Base or Pointer or Enterprise or Byron.".to_string(),
256            BuilderError::ScriptAddressCredentialMismatch => "The address should have script payment credential.".to_string(),
257        }
258    }
259}