use crate::crypto::CryptoError;
use crate::github::GitHubError;
use crate::vault::VaultError;
#[derive(Debug)]
pub enum MurkError {
Vault(VaultError),
Crypto(CryptoError),
Integrity(String),
Key(String),
Recipient(String),
Secret(String),
GitHub(GitHubError),
Io(std::io::Error),
}
impl std::fmt::Display for MurkError {
#[allow(clippy::match_same_arms)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MurkError::Vault(e) => write!(f, "{e}"),
MurkError::Crypto(e) => write!(f, "{e}"),
MurkError::Integrity(msg) => write!(f, "integrity check failed: {msg}"),
MurkError::Key(msg) => write!(f, "{msg}"),
MurkError::Recipient(msg) => write!(f, "{msg}"),
MurkError::Secret(msg) => write!(f, "{msg}"),
MurkError::GitHub(e) => write!(f, "{e}"),
MurkError::Io(e) => write!(f, "I/O error: {e}"),
}
}
}
impl std::error::Error for MurkError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
MurkError::Io(e) => Some(e),
_ => None,
}
}
}
impl From<VaultError> for MurkError {
fn from(e: VaultError) -> Self {
MurkError::Vault(e)
}
}
impl From<CryptoError> for MurkError {
fn from(e: CryptoError) -> Self {
MurkError::Crypto(e)
}
}
impl From<GitHubError> for MurkError {
fn from(e: GitHubError) -> Self {
MurkError::GitHub(e)
}
}
impl From<std::io::Error> for MurkError {
fn from(e: std::io::Error) -> Self {
MurkError::Io(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_integrity() {
let e = MurkError::Integrity("mac mismatch".into());
assert_eq!(e.to_string(), "integrity check failed: mac mismatch");
}
#[test]
fn display_key() {
let e = MurkError::Key("MURK_KEY not set".into());
assert_eq!(e.to_string(), "MURK_KEY not set");
}
#[test]
fn display_recipient() {
let e = MurkError::Recipient("not found".into());
assert_eq!(e.to_string(), "not found");
}
#[test]
fn display_secret() {
let e = MurkError::Secret("invalid".into());
assert_eq!(e.to_string(), "invalid");
}
#[test]
fn display_io() {
let e = MurkError::Io(std::io::Error::new(std::io::ErrorKind::NotFound, "gone"));
assert!(e.to_string().contains("I/O error"));
}
#[test]
fn from_vault_error() {
let ve = VaultError::Parse("bad json".into());
let e: MurkError = ve.into();
assert!(e.to_string().contains("bad json"));
}
#[test]
fn from_crypto_error() {
let ce = CryptoError::Decrypt("failed".into());
let e: MurkError = ce.into();
assert!(e.to_string().contains("failed"));
}
#[test]
fn from_io_error() {
let io = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "denied");
let e: MurkError = io.into();
assert!(e.to_string().contains("denied"));
}
#[test]
fn error_source_io() {
let e = MurkError::Io(std::io::Error::new(std::io::ErrorKind::Other, "test"));
assert!(std::error::Error::source(&e).is_some());
}
#[test]
fn error_source_non_io() {
let e = MurkError::Key("test".into());
assert!(std::error::Error::source(&e).is_none());
}
}