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