use crate::header::KeyId;
pub type Result<T> = std::result::Result<T, SframeError>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SframeError {
#[error("No DecryptionKey has been found")]
MissingDecryptionKey {
key_id: KeyId,
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("Failed to Decrypt")]
DecryptionFailure,
#[error("Failed to Encrypt")]
EncryptionFailure,
#[error("Unable to create unbound encryption key")]
KeyDerivationFailure,
#[error("Unable to ratchet the decryption key")]
RatchetingFailure,
#[error("Cipher suite is not supported by this backend")]
UnsupportedCipherSuite,
#[error("{0}")]
FrameValidationFailed(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("{0}")]
CounterCreationFailed(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("buffer with size {0} is too small")]
InvalidBuffer(usize),
#[error("{name} of {value} is outside {min}..={max}")]
OutOfRange {
name: &'static str,
value: u64,
min: u64,
max: u64,
},
#[error("{0}")]
BufferAllocationFailed(#[source] Box<dyn std::error::Error + Send + Sync>),
}
impl SframeError {
pub fn source_as<E>(&self) -> Option<&E>
where
E: std::error::Error + 'static,
{
std::error::Error::source(self)?.downcast_ref()
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[error("the custom component rejected it")]
struct CustomError;
#[test]
fn recovers_the_error_of_a_custom_component() {
let error = SframeError::FrameValidationFailed(Box::new(CustomError));
assert_eq!(error.source_as::<CustomError>(), Some(&CustomError));
}
#[test]
fn recovers_nothing_of_another_type() {
let error = SframeError::FrameValidationFailed(Box::new(CustomError));
assert!(error.source_as::<std::fmt::Error>().is_none());
}
#[test]
fn recovers_nothing_without_a_source() {
let error = SframeError::DecryptionFailure;
assert!(error.source_as::<CustomError>().is_none());
}
}