core_crypto/error/
mod.rs

1mod cryptobox_migration;
2mod keystore;
3mod leaf;
4mod mls;
5mod proteus;
6mod recursive;
7mod wrapper;
8
9pub use cryptobox_migration::{CryptoboxMigrationError, CryptoboxMigrationErrorKind};
10pub use keystore::KeystoreError;
11pub use leaf::LeafError;
12pub use mls::{MlsError, MlsErrorKind};
13pub use proteus::{ProteusError, ProteusErrorKind};
14pub use recursive::{RecursiveError, ToRecursiveError};
15pub(crate) use wrapper::WrappedContextualError;
16
17/// A module-specific [Result][core::result::Result] type with a default error variant.
18pub type Result<T, E = Error> = core::result::Result<T, E>;
19
20/// Errors produced by the root module group
21#[derive(Debug, thiserror::Error)]
22pub enum Error {
23    /// Invalid [crate::transaction_context::TransactionContext]. This context has been finished and can no longer be used.
24    #[error("This transaction context has already been finished and can no longer be used.")]
25    InvalidTransactionContext,
26    /// The proteus client has been called but has not been initialized yet
27    #[error("Proteus client hasn't been initialized")]
28    ProteusNotInitialized,
29    /// Mls Transport Callbacks were not provided
30    #[error("The mls transport callbacks needed for CoreCrypto to operate were not set")]
31    MlsTransportNotProvided,
32    /// Any error that occurs during mls transport.
33    #[error("Error during mls transport: {0}")]
34    ErrorDuringMlsTransport(String),
35    /// This item requires a feature that the core-crypto library was built without
36    #[error("This item requires a feature that the core-crypto library was built without: {0}")]
37    FeatureDisabled(&'static str),
38    /// A key store operation failed
39    #[error(transparent)]
40    Keystore(#[from] KeystoreError),
41    /// An external MLS operation failed
42    #[error(transparent)]
43    Mls(#[from] MlsError),
44    /// A Proteus operation failed
45    #[error(transparent)]
46    Proteus(#[from] ProteusError),
47    /// A cryptobox migration operation failed
48    #[error(transparent)]
49    CryptoboxMigration(#[from] CryptoboxMigrationError),
50    /// A crate-internal operation failed
51    #[error(transparent)]
52    Recursive(#[from] RecursiveError),
53}
54
55/// Produce the error message from the innermost wrapped error.
56///
57/// We produce arbitrarily nested errors which are very helpful
58/// at capturing relevant context, and very bad at surfacing the
59/// root error cause in a default `.to_string()` call.
60///
61/// This trait, automatically implemented for all standard errors,
62/// rectifies this problem.
63pub trait InnermostErrorMessage {
64    /// Produce the error message from the innermost wrapped error.
65    fn innermost_error_message(&self) -> String;
66}
67
68impl<E: std::error::Error> InnermostErrorMessage for E {
69    fn innermost_error_message(&self) -> String {
70        let mut err: &dyn std::error::Error = self;
71        while let Some(source) = err.source() {
72            err = source;
73        }
74        err.to_string()
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn can_unpack_wrapped_error() {
84        let inner = Error::InvalidTransactionContext;
85        let outer = RecursiveError::root("wrapping the inner for test purposes")(inner);
86        let message = outer.innermost_error_message();
87        assert_eq!(message, Error::InvalidTransactionContext.to_string());
88    }
89}