indy_credx/
error.rs

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    // General errors
12    Input,
13    IOError,
14    InvalidState,
15    Unexpected,
16    // Credential/proof errors
17    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/// The standard crate error type
45#[derive(Debug)]
46pub struct Error {
47    kind: ErrorKind,
48    pub cause: Option<Box<dyn StdError + Send + Sync + 'static>>,
49    pub message: Option<String>,
50    // backtrace (when supported)
51}
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        // FIXME could be input or output...
134        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}