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}