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