indy_utils/
error.rs

1use std::error::Error as StdError;
2use thiserror::Error;
3
4type DynError = Box<dyn StdError + Send + Sync + 'static>;
5
6macro_rules! define_error {
7    ($name:tt, $short:expr, $doc:tt) => {
8        #[derive(Debug, Error)]
9        #[doc=$doc]
10        pub struct $name {
11            pub context: Option<String>,
12            pub source: Option<DynError>,
13        }
14
15        impl $name {
16            pub fn from_msg<T: Into<String>>(msg: T) -> Self {
17                Self::from(msg.into())
18            }
19
20            pub fn from_err<E>(err: E) -> Self
21            where
22                E: StdError + Send + Sync + 'static,
23            {
24                Self {
25                    context: None,
26                    source: Some(Box::new(err) as DynError),
27                }
28            }
29
30            pub fn from_msg_err<M, E>(msg: M, err: E) -> Self
31            where
32                M: Into<String>,
33                E: StdError + Send + Sync + 'static,
34            {
35                Self {
36                    context: Some(msg.into()),
37                    source: Some(Box::new(err) as DynError),
38                }
39            }
40        }
41
42        impl From<&str> for $name {
43            fn from(context: &str) -> Self {
44                Self {
45                    context: Some(context.to_owned()),
46                    source: None,
47                }
48            }
49        }
50
51        impl From<String> for $name {
52            fn from(context: String) -> Self {
53                Self {
54                    context: Some(context),
55                    source: None,
56                }
57            }
58        }
59
60        impl From<Option<String>> for $name {
61            fn from(context: Option<String>) -> Self {
62                Self {
63                    context,
64                    source: None,
65                }
66            }
67        }
68
69        impl<M, E> From<(M, E)> for $name
70        where
71            M: Into<String>,
72            E: StdError + Send + Sync + 'static,
73        {
74            fn from((context, err): (M, E)) -> Self {
75                Self::from_msg_err(context, err)
76            }
77        }
78
79        impl Into<String> for $name {
80            fn into(self) -> String {
81                self.to_string()
82            }
83        }
84
85        impl std::fmt::Display for $name {
86            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87                write!(f, $short)?;
88                match self.context {
89                    Some(ref context) => write!(f, ": {}", context),
90                    None => Ok(()),
91                }
92            }
93        }
94    };
95}
96
97define_error!(
98    ConversionError,
99    "Conversion error",
100    "Error type for general data conversion errors"
101);
102
103define_error!(
104    EncryptionError,
105    "Encryption error",
106    "Error type for failure of encryption and decryption operations"
107);
108
109define_error!(
110    UnexpectedError,
111    "Unexpected error",
112    "Error type for eventualities that shouldn't normally occur"
113);
114
115define_error!(
116    ValidationError,
117    "Validation error",
118    "Error type for failures of `Validatable::validate`"
119);
120
121#[cfg(feature = "serde_json")]
122impl From<serde_json::error::Error> for ConversionError {
123    fn from(err: serde_json::error::Error) -> Self {
124        Self::from_msg(err.to_string())
125    }
126}
127
128impl From<std::str::Utf8Error> for ConversionError {
129    fn from(_err: std::str::Utf8Error) -> Self {
130        Self::from("UTF-8 decoding error")
131    }
132}
133
134impl From<std::string::FromUtf8Error> for ConversionError {
135    fn from(_err: std::string::FromUtf8Error) -> Self {
136        Self::from("UTF-8 decoding error")
137    }
138}
139
140impl From<ValidationError> for ConversionError {
141    fn from(err: ValidationError) -> Self {
142        Self {
143            context: err.context,
144            source: err.source,
145        }
146    }
147}
148
149impl From<ConversionError> for ValidationError {
150    fn from(err: ConversionError) -> Self {
151        Self {
152            context: err.context,
153            source: err.source,
154        }
155    }
156}
157
158impl From<UnexpectedError> for ConversionError {
159    fn from(err: UnexpectedError) -> Self {
160        Self {
161            context: err.context,
162            source: err.source,
163        }
164    }
165}
166
167impl From<UnexpectedError> for EncryptionError {
168    fn from(err: UnexpectedError) -> Self {
169        Self {
170            context: err.context,
171            source: err.source,
172        }
173    }
174}