1use std::convert::Infallible;
5use std::num::TryFromIntError;
6
7use namada_core::arith;
8use thiserror::Error;
9
10use crate::db;
11
12#[allow(missing_docs)]
13#[derive(Error, Debug)]
14pub enum Error {
15 #[error("{0}")]
16 SimpleMessage(&'static str),
17 #[error("{0}")]
18 AllocMessage(String),
19 #[error("{0}")]
20 Custom(CustomError),
21 #[error("{0}: {1}")]
22 CustomWithMessage(&'static str, CustomError),
23}
24
25pub type Result<T> = std::result::Result<T, Error>;
27
28pub trait ResultExt<T> {
32 fn into_storage_result(self) -> Result<T>;
34
35 fn wrap_err(self, msg: &'static str) -> Result<T>;
37}
38
39impl<T, E> ResultExt<T> for std::result::Result<T, E>
40where
41 E: std::error::Error + Send + Sync + 'static,
42{
43 fn into_storage_result(self) -> Result<T> {
44 self.map_err(Error::new)
45 }
46
47 fn wrap_err(self, msg: &'static str) -> Result<T> {
48 self.map_err(|err| Error::wrap(msg, err))
49 }
50}
51
52impl Error {
53 pub fn new<E>(error: E) -> Self
55 where
56 E: Into<Box<dyn std::error::Error + Send + Sync>>,
57 {
58 Self::Custom(CustomError(error.into()))
59 }
60
61 #[inline]
63 pub const fn new_const(msg: &'static str) -> Self {
64 Self::SimpleMessage(msg)
65 }
66
67 #[inline]
69 pub const fn new_alloc(msg: String) -> Self {
70 Self::AllocMessage(msg)
71 }
72
73 pub fn wrap<E>(msg: &'static str, error: E) -> Self
75 where
76 E: Into<Box<dyn std::error::Error + Send + Sync>>,
77 {
78 Self::CustomWithMessage(msg, CustomError(error.into()))
79 }
80
81 pub fn downcast<E>(self) -> std::result::Result<Box<E>, Self>
93 where
94 E: std::error::Error + Send + Sync + 'static,
95 {
96 match self {
97 Self::Custom(CustomError(b))
98 | Self::CustomWithMessage(_, CustomError(b))
99 if b.is::<E>() =>
100 {
101 let res = b.downcast::<E>();
102 Ok(res.unwrap())
103 }
104 _ => Err(self),
105 }
106 }
107
108 pub fn downcast_ref<E>(&self) -> Option<&E>
111 where
112 E: std::error::Error + Send + Sync + 'static,
113 {
114 match self {
115 Self::Custom(CustomError(b))
116 | Self::CustomWithMessage(_, CustomError(b))
117 if b.is::<E>() =>
118 {
119 b.downcast_ref::<E>()
120 }
121 _ => None,
122 }
123 }
124}
125
126#[derive(Debug)]
128pub struct CustomError(pub Box<dyn std::error::Error + Send + Sync>);
129
130impl std::fmt::Display for CustomError {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 self.0.fmt(f)
133 }
134}
135
136pub trait OptionExt<T> {
139 fn ok_or_err_msg(self, msg: &'static str) -> Result<T>;
143}
144
145impl<T> OptionExt<T> for Option<T> {
146 fn ok_or_err_msg(self, msg: &'static str) -> Result<T> {
147 self.ok_or_else(|| Error::new_const(msg))
148 }
149}
150
151impl From<Error> for namada_core::ibc::core::host::types::error::HostError {
155 fn from(error: Error) -> Self {
156 namada_core::ibc::core::host::types::error::HostError::Other {
157 description: format!("Storage error: {error}"),
158 }
159 }
160}
161
162impl From<arith::Error> for Error {
163 fn from(value: arith::Error) -> Self {
164 Error::new(value)
165 }
166}
167
168impl From<db::Error> for Error {
169 fn from(value: db::Error) -> Self {
170 Error::new(value)
171 }
172}
173
174impl From<namada_core::storage::Error> for Error {
175 fn from(value: namada_core::storage::Error) -> Self {
176 Error::new(value)
177 }
178}
179
180impl From<namada_core::DecodeError> for Error {
181 fn from(value: namada_core::DecodeError) -> Self {
182 Error::new(value)
183 }
184}
185impl From<namada_core::string_encoding::DecodeError> for Error {
186 fn from(value: namada_core::string_encoding::DecodeError) -> Self {
187 Error::new(value)
188 }
189}
190
191impl From<namada_core::hash::Error> for Error {
192 fn from(value: namada_core::hash::Error) -> Self {
193 Error::new(value)
194 }
195}
196
197impl From<namada_merkle_tree::Error> for Error {
198 fn from(value: namada_merkle_tree::Error) -> Self {
199 Error::new(value)
200 }
201}
202
203impl From<Infallible> for Error {
204 fn from(_value: Infallible) -> Self {
205 panic!("Infallible error can never be constructed")
206 }
207}
208
209impl From<TryFromIntError> for Error {
210 fn from(value: TryFromIntError) -> Self {
211 Error::new(value)
212 }
213}