use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CasError {
InvalidKey,
InvalidNonce,
InvalidSignature,
InvalidInput,
InvalidPemKey,
InvalidParameters,
EncryptionFailed,
DecryptionFailed,
SigningFailed,
KeyGenerationFailed,
PasswordHashingFailed,
CompressionFailed,
}
impl fmt::Display for CasError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let message = match self {
CasError::InvalidKey => "invalid key: wrong length or could not be parsed",
CasError::InvalidNonce => "invalid nonce: wrong length",
CasError::InvalidSignature => "invalid signature: wrong length or could not be parsed",
CasError::InvalidInput => "invalid input: could not be decoded",
CasError::InvalidPemKey => "invalid PEM key: could not be decoded or encoded",
CasError::InvalidParameters => "invalid algorithm parameters",
CasError::EncryptionFailed => "encryption failed",
CasError::DecryptionFailed => "decryption failed or authentication tag mismatch",
CasError::SigningFailed => "signing failed",
CasError::KeyGenerationFailed => "key generation failed",
CasError::PasswordHashingFailed => "password hashing failed",
CasError::CompressionFailed => "compression or decompression failed",
};
f.write_str(message)
}
}
impl std::error::Error for CasError {}
impl CasError {
pub fn error_code(&self) -> i32 {
match self {
CasError::InvalidKey => 1,
CasError::InvalidNonce => 2,
CasError::InvalidSignature => 3,
CasError::InvalidInput => 4,
CasError::InvalidPemKey => 5,
CasError::InvalidParameters => 6,
CasError::EncryptionFailed => 7,
CasError::DecryptionFailed => 8,
CasError::SigningFailed => 9,
CasError::KeyGenerationFailed => 10,
CasError::PasswordHashingFailed => 11,
CasError::CompressionFailed => 12,
}
}
}
pub type CasResult<T> = Result<T, CasError>;
#[cfg(test)]
mod tests {
use super::CasError;
#[test]
fn error_code_contract_is_stable() {
let expected: &[(CasError, i32)] = &[
(CasError::InvalidKey, 1),
(CasError::InvalidNonce, 2),
(CasError::InvalidSignature, 3),
(CasError::InvalidInput, 4),
(CasError::InvalidPemKey, 5),
(CasError::InvalidParameters, 6),
(CasError::EncryptionFailed, 7),
(CasError::DecryptionFailed, 8),
(CasError::SigningFailed, 9),
(CasError::KeyGenerationFailed, 10),
(CasError::PasswordHashingFailed, 11),
(CasError::CompressionFailed, 12),
];
for (error, code) in expected {
assert_eq!(
error.error_code(),
*code,
"error code for {error:?} changed; this breaks the FFI ABI contract"
);
}
fn assert_all_variants_covered(error: &CasError) {
match error {
CasError::InvalidKey
| CasError::InvalidNonce
| CasError::InvalidSignature
| CasError::InvalidInput
| CasError::InvalidPemKey
| CasError::InvalidParameters
| CasError::EncryptionFailed
| CasError::DecryptionFailed
| CasError::SigningFailed
| CasError::KeyGenerationFailed
| CasError::PasswordHashingFailed
| CasError::CompressionFailed => {}
}
}
let _ = assert_all_variants_covered;
}
}