Skip to main content

core_crypto/error/
mod.rs

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