1use std::error::Error as StdError;
2use std::fmt::{self, Display, Formatter};
3use std::result::Result as StdResult;
4
5use crate::anoncreds_clsignatures::{Error as ClError, ErrorKind as ClErrorKind};
6
7pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum ErrorKind {
11 Input,
13 IOError,
14 InvalidState,
15 Unexpected,
16 CredentialRevoked,
18 InvalidUserRevocId,
19 ProofRejected,
20 RevocationRegistryFull,
21}
22
23impl ErrorKind {
24 pub fn as_str(&self) -> &'static str {
25 match self {
26 Self::Input => "Input error",
27 Self::IOError => "IO error",
28 Self::InvalidState => "Invalid state",
29 Self::Unexpected => "Unexpected error",
30 Self::CredentialRevoked => "Credential revoked",
31 Self::InvalidUserRevocId => "Invalid revocation accumulator index",
32 Self::ProofRejected => "Proof rejected",
33 Self::RevocationRegistryFull => "Revocation registry full",
34 }
35 }
36}
37
38impl Display for ErrorKind {
39 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40 f.write_str(self.as_str())
41 }
42}
43
44#[derive(Debug)]
46pub struct Error {
47 kind: ErrorKind,
48 pub cause: Option<Box<dyn StdError + Send + Sync + 'static>>,
49 pub message: Option<String>,
50 }
52
53impl Error {
54 pub fn from_msg<T: Into<String>>(kind: ErrorKind, msg: T) -> Self {
55 Self {
56 kind,
57 cause: None,
58 message: Some(msg.into()),
59 }
60 }
61
62 pub fn from_opt_msg<T: Into<String>>(kind: ErrorKind, msg: Option<T>) -> Self {
63 Self {
64 kind,
65 cause: None,
66 message: msg.map(Into::into),
67 }
68 }
69
70 pub fn kind(&self) -> ErrorKind {
71 self.kind
72 }
73
74 pub fn with_cause<T: Into<Box<dyn StdError + Send + Sync>>>(mut self, err: T) -> Self {
75 self.cause = Some(err.into());
76 self
77 }
78}
79
80impl fmt::Display for Error {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 match (self.kind, &self.message) {
83 (ErrorKind::Input, None) => write!(f, "{}", self.kind),
84 (ErrorKind::Input, Some(msg)) => f.write_str(msg),
85 (kind, None) => write!(f, "{}", kind),
86 (kind, Some(msg)) => write!(f, "{}: {}", kind, msg),
87 }?;
88 if let Some(ref source) = self.cause {
89 write!(f, " [{}]", source)?;
90 }
91 Ok(())
92 }
93}
94
95impl StdError for Error {
96 fn source(&self) -> Option<&(dyn StdError + 'static)> {
97 self.cause
98 .as_ref()
99 .map(|err| unsafe { std::mem::transmute(&**err) })
100 }
101}
102
103impl PartialEq for Error {
104 fn eq(&self, other: &Self) -> bool {
105 self.kind == other.kind && self.message == other.message
106 }
107}
108
109impl From<ErrorKind> for Error {
110 fn from(kind: ErrorKind) -> Self {
111 Self {
112 kind,
113 cause: None,
114 message: None,
115 }
116 }
117}
118
119impl From<indy_data_types::ValidationError> for Error {
120 fn from(err: indy_data_types::ValidationError) -> Self {
121 Error::from_opt_msg(ErrorKind::Input, err.context)
122 }
123}
124
125impl From<std::io::Error> for Error {
126 fn from(err: std::io::Error) -> Self {
127 Error::from(ErrorKind::IOError).with_cause(err)
128 }
129}
130
131impl From<serde_json::Error> for Error {
132 fn from(err: serde_json::Error) -> Self {
133 Error::from(ErrorKind::Input).with_cause(err)
135 }
136}
137
138impl From<ClError> for Error {
139 fn from(err: ClError) -> Self {
140 let message = err.to_string();
141 let kind = match err.kind() {
142 ClErrorKind::InvalidState => ErrorKind::InvalidState,
143 ClErrorKind::ProofRejected => ErrorKind::ProofRejected,
144 };
145 Error::from_msg(kind, message)
146 }
147}
148
149impl<M> From<(ErrorKind, M)> for Error
150where
151 M: fmt::Display + Send + Sync + 'static,
152{
153 fn from((kind, msg): (ErrorKind, M)) -> Error {
154 Error::from_msg(kind, msg.to_string())
155 }
156}
157
158macro_rules! err_msg {
159 () => {
160 $crate::error::Error::from($crate::error::ErrorKind::Input)
161 };
162 ($kind:ident) => {
163 $crate::error::Error::from($crate::error::ErrorKind::$kind)
164 };
165 ($kind:ident, $($args:tt)+) => {
166 $crate::error::Error::from_msg($crate::error::ErrorKind::$kind, format!($($args)+))
167 };
168 ($($args:tt)+) => {
169 $crate::error::Error::from_msg($crate::error::ErrorKind::Input, format!($($args)+))
170 };
171}
172
173macro_rules! err_map {
174 ($($params:tt)*) => {
175 |err| err_msg!($($params)*).with_cause(err)
176 };
177}
178
179pub trait ResultExt<T, E> {
180 fn map_err_string(self) -> StdResult<T, String>;
181 fn map_input_err<F, M>(self, mapfn: F) -> Result<T>
182 where
183 F: FnOnce() -> M,
184 M: fmt::Display + Send + Sync + 'static;
185 fn with_err_msg<M>(self, kind: ErrorKind, msg: M) -> Result<T>
186 where
187 M: fmt::Display + Send + Sync + 'static;
188 fn with_input_err<M>(self, msg: M) -> Result<T>
189 where
190 M: fmt::Display + Send + Sync + 'static;
191}
192
193impl<T, E> ResultExt<T, E> for StdResult<T, E>
194where
195 E: std::error::Error + Send + Sync + 'static,
196{
197 fn map_err_string(self) -> StdResult<T, String> {
198 self.map_err(|err| err.to_string())
199 }
200
201 fn map_input_err<F, M>(self, mapfn: F) -> Result<T>
202 where
203 F: FnOnce() -> M,
204 M: fmt::Display + Send + Sync + 'static,
205 {
206 self.map_err(|err| Error::from_msg(ErrorKind::Input, mapfn().to_string()).with_cause(err))
207 }
208
209 fn with_err_msg<M>(self, kind: ErrorKind, msg: M) -> Result<T>
210 where
211 M: fmt::Display + Send + Sync + 'static,
212 {
213 self.map_err(|err| Error::from_msg(kind, msg.to_string()).with_cause(err))
214 }
215
216 #[inline]
217 fn with_input_err<M>(self, msg: M) -> Result<T>
218 where
219 M: fmt::Display + Send + Sync + 'static,
220 {
221 self.map_err(|err| Error::from_msg(ErrorKind::Input, msg.to_string()).with_cause(err))
222 }
223}