core_crypto/error/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
// Wire
// Copyright (C) 2022 Wire Swiss GmbH
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
mod cryptobox_migration;
mod keystore;
mod leaf;
mod mls;
mod proteus;
mod recursive;
mod wrapper;
pub use cryptobox_migration::{CryptoboxMigrationError, CryptoboxMigrationErrorKind};
pub use keystore::KeystoreError;
pub use leaf::LeafError;
pub use mls::{MlsError, MlsErrorKind};
pub use proteus::{ProteusError, ProteusErrorKind};
pub use recursive::{RecursiveError, ToRecursiveError};
pub(crate) use wrapper::WrappedContextualError;
/// A module-specific [Result][core::result::Result] type with a default error variant.
pub type Result<T, E = Error> = core::result::Result<T, E>;
/// Errors produced by the root module group
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Invalid Context. This context has been finished and can no longer be used.
#[error("This context has already been finished and can no longer be used.")]
InvalidContext,
/// The proteus client has been called but has not been initialized yet
#[error("Proteus client hasn't been initialized")]
ProteusNotInitialized,
/// Mls Transport Callbacks were not provided
#[error("The mls transport callbacks needed for CoreCrypto to operate were not set")]
MlsTransportNotProvided,
/// Any error that occurs during mls transport.
#[error("Error during mls transport: {0}")]
ErrorDuringMlsTransport(String),
/// This item requires a feature that the core-crypto library was built without
#[error("This item requires a feature that the core-crypto library was built without: {0}")]
FeatureDisabled(&'static str),
/// A key store operation failed
#[error(transparent)]
Keystore(#[from] KeystoreError),
/// An external MLS operation failed
#[error(transparent)]
Mls(#[from] MlsError),
/// A Proteus operation failed
#[error(transparent)]
Proteus(#[from] ProteusError),
/// A cryptobox migration operation failed
#[error(transparent)]
CryptoboxMigration(#[from] CryptoboxMigrationError),
/// A crate-internal operation failed
#[error(transparent)]
Recursive(#[from] RecursiveError),
}
/// Produce the error message from the innermost wrapped error.
///
/// We produce arbitrarily nested errors which are very helpful
/// at capturing relevant context, and very bad at surfacing the
/// root error cause in a default `.to_string()` call.
///
/// This trait, automatically implemented for all standard errors,
/// rectifies this problem.
pub trait InnermostErrorMessage {
/// Produce the error message from the innermost wrapped error.
fn innermost_error_message(&self) -> String;
}
impl<E: std::error::Error> InnermostErrorMessage for E {
fn innermost_error_message(&self) -> String {
let mut err: &dyn std::error::Error = self;
while let Some(source) = err.source() {
err = source;
}
err.to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_unpack_wrapped_error() {
let inner = Error::InvalidContext;
let outer = RecursiveError::root("wrapping the inner for test purposes")(inner);
let message = outer.innermost_error_message();
assert_eq!(message, Error::InvalidContext.to_string());
}
}