1use crate::crypto::CryptoError;
4use crate::github::GitHubError;
5use crate::vault::VaultError;
6
7#[derive(Debug)]
9pub enum MurkError {
10 Vault(VaultError),
12 Crypto(CryptoError),
14 Integrity(String),
16 Key(String),
18 Recipient(String),
20 Secret(String),
22 GitHub(GitHubError),
24 Io(std::io::Error),
26}
27
28impl std::fmt::Display for MurkError {
29 #[allow(clippy::match_same_arms)]
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 MurkError::Vault(e) => write!(f, "{e}"),
33 MurkError::Crypto(e) => write!(f, "{e}"),
34 MurkError::Integrity(msg) => write!(f, "integrity check failed: {msg}"),
35 MurkError::Key(msg) => write!(f, "{msg}"),
36 MurkError::Recipient(msg) => write!(f, "{msg}"),
37 MurkError::Secret(msg) => write!(f, "{msg}"),
38 MurkError::GitHub(e) => write!(f, "{e}"),
39 MurkError::Io(e) => write!(f, "I/O error: {e}"),
40 }
41 }
42}
43
44impl std::error::Error for MurkError {
45 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
46 match self {
47 MurkError::Io(e) => Some(e),
48 _ => None,
49 }
50 }
51}
52
53impl From<VaultError> for MurkError {
54 fn from(e: VaultError) -> Self {
55 MurkError::Vault(e)
56 }
57}
58
59impl From<CryptoError> for MurkError {
60 fn from(e: CryptoError) -> Self {
61 MurkError::Crypto(e)
62 }
63}
64
65impl From<GitHubError> for MurkError {
66 fn from(e: GitHubError) -> Self {
67 MurkError::GitHub(e)
68 }
69}
70
71impl From<std::io::Error> for MurkError {
72 fn from(e: std::io::Error) -> Self {
73 MurkError::Io(e)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn display_integrity() {
83 let e = MurkError::Integrity("mac mismatch".into());
84 assert_eq!(e.to_string(), "integrity check failed: mac mismatch");
85 }
86
87 #[test]
88 fn display_key() {
89 let e = MurkError::Key("MURK_KEY not set".into());
90 assert_eq!(e.to_string(), "MURK_KEY not set");
91 }
92
93 #[test]
94 fn display_recipient() {
95 let e = MurkError::Recipient("not found".into());
96 assert_eq!(e.to_string(), "not found");
97 }
98
99 #[test]
100 fn display_secret() {
101 let e = MurkError::Secret("invalid".into());
102 assert_eq!(e.to_string(), "invalid");
103 }
104
105 #[test]
106 fn display_io() {
107 let e = MurkError::Io(std::io::Error::new(std::io::ErrorKind::NotFound, "gone"));
108 assert!(e.to_string().contains("I/O error"));
109 }
110
111 #[test]
112 fn from_vault_error() {
113 let ve = VaultError::Parse("bad json".into());
114 let e: MurkError = ve.into();
115 assert!(e.to_string().contains("bad json"));
116 }
117
118 #[test]
119 fn from_crypto_error() {
120 let ce = CryptoError::Decrypt("failed".into());
121 let e: MurkError = ce.into();
122 assert!(e.to_string().contains("failed"));
123 }
124
125 #[test]
126 fn from_io_error() {
127 let io = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "denied");
128 let e: MurkError = io.into();
129 assert!(e.to_string().contains("denied"));
130 }
131
132 #[test]
133 fn error_source_io() {
134 let e = MurkError::Io(std::io::Error::new(std::io::ErrorKind::Other, "test"));
135 assert!(std::error::Error::source(&e).is_some());
136 }
137
138 #[test]
139 fn error_source_non_io() {
140 let e = MurkError::Key("test".into());
141 assert!(std::error::Error::source(&e).is_none());
142 }
143}