use alloc::string::String;
use core::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
InvalidKey {
expected: usize,
actual: usize,
},
InvalidCiphertext(String),
AuthenticationFailed,
AlgorithmNotEnabled(&'static str),
RandomFailure(&'static str),
}
pub type Result<T> = core::result::Result<T, Error>;
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidKey { expected, actual } => {
write!(
f,
"invalid key length: expected {expected} bytes, got {actual}"
)
}
Self::InvalidCiphertext(why) => write!(f, "invalid ciphertext: {why}"),
Self::AuthenticationFailed => f.write_str("authentication failed"),
Self::AlgorithmNotEnabled(name) => {
write!(f, "algorithm not enabled at compile time: {name}")
}
Self::RandomFailure(why) => write!(f, "OS random source failed: {why}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod tests {
use super::*;
use alloc::format;
use alloc::string::ToString;
#[test]
fn invalid_key_message_includes_lengths() {
let e = Error::InvalidKey {
expected: 32,
actual: 16,
};
let rendered = format!("{e}");
assert!(rendered.contains("32"));
assert!(rendered.contains("16"));
}
#[test]
fn authentication_failure_is_opaque() {
let rendered = Error::AuthenticationFailed.to_string();
assert_eq!(rendered, "authentication failed");
}
#[test]
fn debug_does_not_panic_for_any_variant() {
for e in [
Error::InvalidKey {
expected: 32,
actual: 0,
},
Error::InvalidCiphertext("x".to_string()),
Error::AuthenticationFailed,
Error::AlgorithmNotEnabled("none"),
Error::RandomFailure("ENOSYS"),
] {
let _ = format!("{e:?}");
}
}
}