aries_askar/
error.rs

1use std::error::Error as StdError;
2use std::fmt::{self, Display, Formatter};
3
4use crate::crypto::{Error as CryptoError, ErrorKind as CryptoErrorKind};
5use crate::storage::{Error as StorageError, ErrorKind as StorageErrorKind};
6
7/// The possible kinds of error produced by the crate
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum ErrorKind {
10    /// An unexpected error from the store backend
11    Backend,
12
13    /// The store backend was too busy to handle the request
14    Busy,
15
16    /// A custom error type for external integrations
17    Custom,
18
19    /// An insert operation failed due to a unique key conflict
20    Duplicate,
21
22    /// An encryption or decryption operation failed
23    Encryption,
24
25    /// The input parameters to the method were incorrect
26    Input,
27
28    /// The requested record was not found
29    NotFound,
30
31    /// An unexpected error occurred
32    Unexpected,
33
34    /// An unsupported operation was requested
35    Unsupported,
36}
37
38impl ErrorKind {
39    /// Convert the error kind to a string reference
40    pub fn as_str(&self) -> &'static str {
41        match self {
42            Self::Backend => "Backend error",
43            Self::Busy => "Busy",
44            Self::Custom => "Custom error",
45            Self::Duplicate => "Duplicate",
46            Self::Encryption => "Encryption error",
47            Self::Input => "Input error",
48            Self::NotFound => "Not found",
49            Self::Unexpected => "Unexpected error",
50            Self::Unsupported => "Unsupported",
51        }
52    }
53}
54
55impl Display for ErrorKind {
56    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57        f.write_str(self.as_str())
58    }
59}
60
61/// The standard crate error type
62#[derive(Debug)]
63pub struct Error {
64    pub(crate) kind: ErrorKind,
65    pub(crate) cause: Option<Box<dyn StdError + Send + Sync + 'static>>,
66    pub(crate) message: Option<String>,
67}
68
69impl Error {
70    pub(crate) fn from_msg<T: Into<String>>(kind: ErrorKind, msg: T) -> Self {
71        Self {
72            kind,
73            cause: None,
74            message: Some(msg.into()),
75        }
76    }
77
78    /// Accessor for the error kind
79    pub fn kind(&self) -> ErrorKind {
80        self.kind
81    }
82
83    /// Accessor for the error message
84    pub fn message(&self) -> Option<&str> {
85        self.message.as_deref()
86    }
87
88    pub(crate) fn with_cause<T: Into<Box<dyn StdError + Send + Sync + 'static>>>(
89        mut self,
90        err: T,
91    ) -> Self {
92        self.cause = Some(err.into());
93        self
94    }
95}
96
97impl Display for Error {
98    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
99        if let Some(msg) = self.message.as_ref() {
100            f.write_str(msg)?;
101        } else {
102            f.write_str(self.kind.as_str())?;
103        }
104        if let Some(cause) = self.cause.as_ref() {
105            write!(f, "\nCaused by: {}", cause)?;
106        }
107        Ok(())
108    }
109}
110
111impl StdError for Error {
112    fn source(&self) -> Option<&(dyn StdError + 'static)> {
113        self.cause
114            .as_ref()
115            .map(|err| &**err as &(dyn StdError + 'static))
116    }
117}
118
119impl PartialEq for Error {
120    fn eq(&self, other: &Self) -> bool {
121        self.kind == other.kind && self.message == other.message
122    }
123}
124
125impl From<ErrorKind> for Error {
126    fn from(kind: ErrorKind) -> Self {
127        Self {
128            kind,
129            cause: None,
130            message: None,
131        }
132    }
133}
134
135impl From<CryptoError> for Error {
136    fn from(err: CryptoError) -> Self {
137        let kind = match err.kind() {
138            CryptoErrorKind::Custom => ErrorKind::Custom,
139            CryptoErrorKind::Encryption => ErrorKind::Encryption,
140            CryptoErrorKind::ExceededBuffer | CryptoErrorKind::Unexpected => ErrorKind::Unexpected,
141            CryptoErrorKind::Invalid
142            | CryptoErrorKind::InvalidKeyData
143            | CryptoErrorKind::InvalidNonce
144            | CryptoErrorKind::MissingSecretKey
145            | CryptoErrorKind::Usage => ErrorKind::Input,
146            CryptoErrorKind::Unsupported => ErrorKind::Unsupported,
147        };
148        Error::from_msg(kind, err.message())
149    }
150}
151
152impl From<StorageError> for Error {
153    fn from(err: StorageError) -> Self {
154        let (kind, cause, message) = err.into_parts();
155        let kind = match kind {
156            StorageErrorKind::Backend => ErrorKind::Backend,
157            StorageErrorKind::Busy => ErrorKind::Busy,
158            StorageErrorKind::Custom => ErrorKind::Custom,
159            StorageErrorKind::Duplicate => ErrorKind::Duplicate,
160            StorageErrorKind::Encryption => ErrorKind::Encryption,
161            StorageErrorKind::Input => ErrorKind::Input,
162            StorageErrorKind::NotFound => ErrorKind::NotFound,
163            StorageErrorKind::Unexpected => ErrorKind::Unexpected,
164            StorageErrorKind::Unsupported => ErrorKind::Unsupported,
165        };
166        Error {
167            kind,
168            cause,
169            message,
170        }
171    }
172}
173
174macro_rules! err_msg {
175    () => {
176        $crate::error::Error::from($crate::error::ErrorKind::Input)
177    };
178    ($kind:ident) => {
179        $crate::error::Error::from($crate::error::ErrorKind::$kind)
180    };
181    ($kind:ident, $($args:tt)+) => {
182        $crate::error::Error::from_msg($crate::error::ErrorKind::$kind, format!($($args)+))
183    };
184    ($($args:tt)+) => {
185        $crate::error::Error::from_msg($crate::error::ErrorKind::Input, format!($($args)+))
186    };
187}
188
189macro_rules! err_map {
190    ($($params:tt)*) => {
191        |err| err_msg!($($params)*).with_cause(err)
192    };
193}