indy_crypto/errors/
mod.rs1extern crate serde_json;
2extern crate log;
3
4use ffi::ErrorCode;
5
6use std::fmt;
7use std::cell::RefCell;
8use std::ptr;
9use std::ffi::CString;
10
11use failure::{Backtrace, Context, Fail};
12use libc::c_char;
13
14use utils::ctypes;
15
16pub mod prelude {
17 pub use super::{err_msg, IndyCryptoError, IndyCryptoErrorExt, IndyCryptoErrorKind, IndyCryptoResult, set_current_error, get_current_error_c_json};
18}
19
20#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)]
21pub enum IndyCryptoErrorKind {
22 #[fail(display = "Invalid library state")]
24 InvalidState,
25 #[fail(display = "Invalid structure")]
26 InvalidStructure,
27 #[fail(display = "Invalid parameter {}", 0)]
28 InvalidParam(u32),
29 #[fail(display = "IO error")]
30 IOError,
31 #[fail(display = "Proof rejected")]
33 ProofRejected,
34 #[fail(display = "Revocation accumulator is full")]
35 RevocationAccumulatorIsFull,
36 #[fail(display = "Invalid revocation id")]
37 InvalidRevocationAccumulatorIndex,
38 #[fail(display = "Credential revoked")]
39 CredentialRevoked,
40}
41
42#[derive(Debug)]
43pub struct IndyCryptoError {
44 inner: Context<IndyCryptoErrorKind>
45}
46
47impl Fail for IndyCryptoError {
48 fn cause(&self) -> Option<&Fail> {
49 self.inner.cause()
50 }
51
52 fn backtrace(&self) -> Option<&Backtrace> {
53 self.inner.backtrace()
54 }
55}
56
57impl IndyCryptoError {
58 pub fn from_msg<D>(kind: IndyCryptoErrorKind, msg: D) -> IndyCryptoError
59 where D: fmt::Display + fmt::Debug + Send + Sync + 'static {
60 IndyCryptoError { inner: Context::new(msg).context(kind) }
61 }
62
63 pub fn kind(&self) -> IndyCryptoErrorKind {
64 *self.inner.get_context()
65 }
66}
67
68impl fmt::Display for IndyCryptoError {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 let mut first = true;
71
72 for cause in Fail::iter_chain(&self.inner) {
73 if first {
74 first = false;
75 writeln!(f, "Error: {}", cause)?;
76 } else {
77 writeln!(f, "Caused by: {}", cause)?;
78 }
79 }
80
81 Ok(())
82 }
83}
84
85pub fn err_msg<D>(kind: IndyCryptoErrorKind, msg: D) -> IndyCryptoError
86 where D: fmt::Display + fmt::Debug + Send + Sync + 'static {
87 IndyCryptoError::from_msg(kind, msg)
88}
89
90impl From<Context<IndyCryptoErrorKind>> for IndyCryptoError {
91 fn from(inner: Context<IndyCryptoErrorKind>) -> IndyCryptoError {
92 IndyCryptoError { inner }
93 }
94}
95
96impl From<log::SetLoggerError> for IndyCryptoError {
97 fn from(err: log::SetLoggerError) -> IndyCryptoError {
98 err.context(IndyCryptoErrorKind::InvalidState).into()
99 }
100}
101
102impl From<IndyCryptoErrorKind> for ErrorCode {
103 fn from(code: IndyCryptoErrorKind) -> ErrorCode {
104 match code {
105 IndyCryptoErrorKind::InvalidState => ErrorCode::CommonInvalidState,
106 IndyCryptoErrorKind::InvalidStructure => ErrorCode::CommonInvalidStructure,
107 IndyCryptoErrorKind::InvalidParam(num) =>
108 match num {
109 1 => ErrorCode::CommonInvalidParam1,
110 2 => ErrorCode::CommonInvalidParam2,
111 3 => ErrorCode::CommonInvalidParam3,
112 4 => ErrorCode::CommonInvalidParam4,
113 5 => ErrorCode::CommonInvalidParam5,
114 6 => ErrorCode::CommonInvalidParam6,
115 7 => ErrorCode::CommonInvalidParam7,
116 8 => ErrorCode::CommonInvalidParam8,
117 9 => ErrorCode::CommonInvalidParam9,
118 10 => ErrorCode::CommonInvalidParam10,
119 11 => ErrorCode::CommonInvalidParam11,
120 12 => ErrorCode::CommonInvalidParam12,
121 _ => ErrorCode::CommonInvalidState
122 },
123 IndyCryptoErrorKind::IOError => ErrorCode::CommonIOError,
124 IndyCryptoErrorKind::ProofRejected => ErrorCode::AnoncredsProofRejected,
125 IndyCryptoErrorKind::RevocationAccumulatorIsFull => ErrorCode::AnoncredsRevocationAccumulatorIsFull,
126 IndyCryptoErrorKind::InvalidRevocationAccumulatorIndex => ErrorCode::AnoncredsInvalidRevocationAccumulatorIndex,
127 IndyCryptoErrorKind::CredentialRevoked => ErrorCode::AnoncredsCredentialRevoked,
128 }
129 }
130}
131
132impl From<ErrorCode> for IndyCryptoErrorKind {
133 fn from(err: ErrorCode) -> IndyCryptoErrorKind {
134 match err {
135 ErrorCode::CommonInvalidState => IndyCryptoErrorKind::InvalidState,
136 ErrorCode::CommonInvalidStructure => IndyCryptoErrorKind::InvalidStructure,
137 ErrorCode::CommonInvalidParam1 => IndyCryptoErrorKind::InvalidParam(1),
138 ErrorCode::CommonInvalidParam2 => IndyCryptoErrorKind::InvalidParam(2),
139 ErrorCode::CommonInvalidParam3 => IndyCryptoErrorKind::InvalidParam(3),
140 ErrorCode::CommonInvalidParam4 => IndyCryptoErrorKind::InvalidParam(4),
141 ErrorCode::CommonInvalidParam5 => IndyCryptoErrorKind::InvalidParam(5),
142 ErrorCode::CommonInvalidParam6 => IndyCryptoErrorKind::InvalidParam(6),
143 ErrorCode::CommonInvalidParam7 => IndyCryptoErrorKind::InvalidParam(7),
144 ErrorCode::CommonInvalidParam8 => IndyCryptoErrorKind::InvalidParam(8),
145 ErrorCode::CommonInvalidParam9 => IndyCryptoErrorKind::InvalidParam(9),
146 ErrorCode::CommonInvalidParam10 => IndyCryptoErrorKind::InvalidParam(10),
147 ErrorCode::CommonInvalidParam11 => IndyCryptoErrorKind::InvalidParam(11),
148 ErrorCode::CommonInvalidParam12 => IndyCryptoErrorKind::InvalidParam(12),
149 ErrorCode::CommonIOError => IndyCryptoErrorKind::IOError,
150 ErrorCode::AnoncredsProofRejected => IndyCryptoErrorKind::ProofRejected,
151 ErrorCode::AnoncredsRevocationAccumulatorIsFull => IndyCryptoErrorKind::RevocationAccumulatorIsFull,
152 ErrorCode::AnoncredsInvalidRevocationAccumulatorIndex => IndyCryptoErrorKind::InvalidRevocationAccumulatorIndex,
153 ErrorCode::AnoncredsCredentialRevoked => IndyCryptoErrorKind::CredentialRevoked,
154 _code => IndyCryptoErrorKind::InvalidState
155 }
156 }
157}
158
159impl From<IndyCryptoError> for ErrorCode {
160 fn from(err: IndyCryptoError) -> ErrorCode {
161 set_current_error(&err);
162 err.kind().into()
163 }
164}
165
166pub type IndyCryptoResult<T> = Result<T, IndyCryptoError>;
167
168pub trait IndyCryptoErrorExt {
170 fn to_indy<D>(self, kind: IndyCryptoErrorKind, msg: D) -> IndyCryptoError where D: fmt::Display + Send + Sync + 'static;
171}
172
173impl<E> IndyCryptoErrorExt for E where E: Fail
174{
175 fn to_indy<D>(self, kind: IndyCryptoErrorKind, msg: D) -> IndyCryptoError where D: fmt::Display + Send + Sync + 'static {
176 self.context(msg).context(kind).into()
177 }
178}
179
180thread_local! {
181 pub static CURRENT_ERROR_C_JSON: RefCell<Option<CString>> = RefCell::new(None);
182}
183
184pub fn set_current_error(err: &IndyCryptoError) {
185 CURRENT_ERROR_C_JSON.with(|error| {
186 let error_json = json!({
187 "message": err.to_string(),
188 "backtrace": err.backtrace().map(|bt| bt.to_string())
189 }).to_string();
190 error.replace(Some(ctypes::string_to_cstring(error_json)));
191 });
192}
193
194pub fn get_current_error_c_json() -> *const c_char {
195 let mut value = ptr::null();
196
197 CURRENT_ERROR_C_JSON.with(|err|
198 err.borrow().as_ref().map(|err| value = err.as_ptr())
199 );
200
201 value
202}