1use std::fmt;
7use std::str::FromStr;
8
9use serde::{Deserialize, Deserializer, Serialize};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum AtmErrorCode {
14 ConfigHomeUnavailable,
16 ConfigParseFailed,
18 ConfigRetiredHookMembersKey,
20 ConfigRetiredLegacyHookKeys,
22 ConfigTeamParseFailed,
24 ConfigTeamMissing,
26 IdentityUnavailable,
28 AddressParseFailed,
30 TeamUnavailable,
32 TeamNotFound,
34 AgentNotFound,
36 MailboxReadFailed,
38 MailboxWriteFailed,
40 MailboxLockFailed,
42 MailboxLockReadOnlyFilesystem,
44 MailboxLockTimeout,
46 MessageValidationFailed,
48 SerializationFailed,
50 FilePolicyRejected,
52 FileReferenceRewriteFailed,
54 WaitTimeout,
56 AckInvalidState,
58 ClearInvalidState,
60 ObservabilityEmitFailed,
62 ObservabilityQueryFailed,
64 ObservabilityFollowFailed,
66 ObservabilityHealthFailed,
68 ObservabilityBootstrapFailed,
70 ObservabilityHealthOk,
72 WarningInvalidTeamMemberSkipped,
74 WarningMailboxRecordSkipped,
76 WarningMalformedAtmFieldIgnored,
78 WarningObservabilityHealthDegraded,
80 WarningOriginInboxEntrySkipped,
82 WarningMissingTeamConfigFallback,
84 WarningSendAlertStateDegraded,
86 WarningIdentityDrift,
88 WarningBaselineMemberMissing,
90 WarningRestoreInProgress,
92 WarningStaleMailboxLock,
94 WarningHookSkipped,
96 WarningHookExecutionFailed,
98}
99
100impl AtmErrorCode {
101 pub const fn as_str(self) -> &'static str {
102 match self {
103 Self::ConfigHomeUnavailable => "ATM_CONFIG_HOME_UNAVAILABLE",
104 Self::ConfigParseFailed => "ATM_CONFIG_PARSE_FAILED",
105 Self::ConfigRetiredHookMembersKey => "ATM_CONFIG_RETIRED_HOOK_MEMBERS_KEY",
106 Self::ConfigRetiredLegacyHookKeys => "ATM_CONFIG_RETIRED_LEGACY_HOOK_KEYS",
107 Self::ConfigTeamParseFailed => "ATM_CONFIG_TEAM_PARSE_FAILED",
108 Self::ConfigTeamMissing => "ATM_CONFIG_TEAM_MISSING",
109 Self::IdentityUnavailable => "ATM_IDENTITY_UNAVAILABLE",
110 Self::AddressParseFailed => "ATM_ADDRESS_PARSE_FAILED",
111 Self::TeamUnavailable => "ATM_TEAM_UNAVAILABLE",
112 Self::TeamNotFound => "ATM_TEAM_NOT_FOUND",
113 Self::AgentNotFound => "ATM_AGENT_NOT_FOUND",
114 Self::MailboxReadFailed => "ATM_MAILBOX_READ_FAILED",
115 Self::MailboxWriteFailed => "ATM_MAILBOX_WRITE_FAILED",
116 Self::MailboxLockFailed => "ATM_MAILBOX_LOCK_FAILED",
117 Self::MailboxLockReadOnlyFilesystem => "ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM",
118 Self::MailboxLockTimeout => "ATM_MAILBOX_LOCK_TIMEOUT",
119 Self::MessageValidationFailed => "ATM_MESSAGE_VALIDATION_FAILED",
120 Self::SerializationFailed => "ATM_SERIALIZATION_FAILED",
121 Self::FilePolicyRejected => "ATM_FILE_POLICY_REJECTED",
122 Self::FileReferenceRewriteFailed => "ATM_FILE_REFERENCE_REWRITE_FAILED",
123 Self::WaitTimeout => "ATM_WAIT_TIMEOUT",
124 Self::AckInvalidState => "ATM_ACK_INVALID_STATE",
125 Self::ClearInvalidState => "ATM_CLEAR_INVALID_STATE",
126 Self::ObservabilityEmitFailed => "ATM_OBSERVABILITY_EMIT_FAILED",
127 Self::ObservabilityQueryFailed => "ATM_OBSERVABILITY_QUERY_FAILED",
128 Self::ObservabilityFollowFailed => "ATM_OBSERVABILITY_FOLLOW_FAILED",
129 Self::ObservabilityHealthFailed => "ATM_OBSERVABILITY_HEALTH_FAILED",
130 Self::ObservabilityBootstrapFailed => "ATM_OBSERVABILITY_BOOTSTRAP_FAILED",
131 Self::ObservabilityHealthOk => "ATM_OBSERVABILITY_HEALTH_OK",
132 Self::WarningInvalidTeamMemberSkipped => "ATM_WARNING_INVALID_TEAM_MEMBER_SKIPPED",
133 Self::WarningMailboxRecordSkipped => "ATM_WARNING_MAILBOX_RECORD_SKIPPED",
134 Self::WarningMalformedAtmFieldIgnored => "ATM_WARNING_MALFORMED_ATM_FIELD_IGNORED",
135 Self::WarningObservabilityHealthDegraded => "ATM_WARNING_OBSERVABILITY_HEALTH_DEGRADED",
136 Self::WarningOriginInboxEntrySkipped => "ATM_WARNING_ORIGIN_INBOX_ENTRY_SKIPPED",
137 Self::WarningMissingTeamConfigFallback => "ATM_WARNING_MISSING_TEAM_CONFIG_FALLBACK",
138 Self::WarningSendAlertStateDegraded => "ATM_WARNING_SEND_ALERT_STATE_DEGRADED",
139 Self::WarningIdentityDrift => "ATM_WARNING_IDENTITY_DRIFT",
140 Self::WarningBaselineMemberMissing => "ATM_WARNING_BASELINE_MEMBER_MISSING",
141 Self::WarningRestoreInProgress => "ATM_WARNING_RESTORE_IN_PROGRESS",
142 Self::WarningStaleMailboxLock => "ATM_WARNING_STALE_MAILBOX_LOCK",
143 Self::WarningHookSkipped => "ATM_WARNING_HOOK_SKIPPED",
144 Self::WarningHookExecutionFailed => "ATM_WARNING_HOOK_EXECUTION_FAILED",
145 }
146 }
147}
148
149impl FromStr for AtmErrorCode {
150 type Err = &'static str;
151
152 fn from_str(value: &str) -> Result<Self, Self::Err> {
153 match value {
154 "ATM_CONFIG_HOME_UNAVAILABLE" => Ok(Self::ConfigHomeUnavailable),
155 "ATM_CONFIG_PARSE_FAILED" => Ok(Self::ConfigParseFailed),
156 "ATM_CONFIG_RETIRED_HOOK_MEMBERS_KEY" => Ok(Self::ConfigRetiredHookMembersKey),
157 "ATM_CONFIG_RETIRED_LEGACY_HOOK_KEYS" => Ok(Self::ConfigRetiredLegacyHookKeys),
158 "ATM_CONFIG_TEAM_PARSE_FAILED" => Ok(Self::ConfigTeamParseFailed),
159 "ATM_CONFIG_TEAM_MISSING" => Ok(Self::ConfigTeamMissing),
160 "ATM_IDENTITY_UNAVAILABLE" => Ok(Self::IdentityUnavailable),
161 "ATM_ADDRESS_PARSE_FAILED" => Ok(Self::AddressParseFailed),
162 "ATM_TEAM_UNAVAILABLE" => Ok(Self::TeamUnavailable),
163 "ATM_TEAM_NOT_FOUND" => Ok(Self::TeamNotFound),
164 "ATM_AGENT_NOT_FOUND" => Ok(Self::AgentNotFound),
165 "ATM_MAILBOX_READ_FAILED" => Ok(Self::MailboxReadFailed),
166 "ATM_MAILBOX_WRITE_FAILED" => Ok(Self::MailboxWriteFailed),
167 "ATM_MAILBOX_LOCK_FAILED" => Ok(Self::MailboxLockFailed),
168 "ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM" => Ok(Self::MailboxLockReadOnlyFilesystem),
169 "ATM_MAILBOX_LOCK_TIMEOUT" => Ok(Self::MailboxLockTimeout),
170 "ATM_MESSAGE_VALIDATION_FAILED" => Ok(Self::MessageValidationFailed),
171 "ATM_SERIALIZATION_FAILED" => Ok(Self::SerializationFailed),
172 "ATM_FILE_POLICY_REJECTED" => Ok(Self::FilePolicyRejected),
173 "ATM_FILE_REFERENCE_REWRITE_FAILED" => Ok(Self::FileReferenceRewriteFailed),
174 "ATM_WAIT_TIMEOUT" => Ok(Self::WaitTimeout),
175 "ATM_ACK_INVALID_STATE" => Ok(Self::AckInvalidState),
176 "ATM_CLEAR_INVALID_STATE" => Ok(Self::ClearInvalidState),
177 "ATM_OBSERVABILITY_EMIT_FAILED" => Ok(Self::ObservabilityEmitFailed),
178 "ATM_OBSERVABILITY_QUERY_FAILED" => Ok(Self::ObservabilityQueryFailed),
179 "ATM_OBSERVABILITY_FOLLOW_FAILED" => Ok(Self::ObservabilityFollowFailed),
180 "ATM_OBSERVABILITY_HEALTH_FAILED" => Ok(Self::ObservabilityHealthFailed),
181 "ATM_OBSERVABILITY_BOOTSTRAP_FAILED" => Ok(Self::ObservabilityBootstrapFailed),
182 "ATM_OBSERVABILITY_HEALTH_OK" => Ok(Self::ObservabilityHealthOk),
183 "ATM_WARNING_INVALID_TEAM_MEMBER_SKIPPED" => Ok(Self::WarningInvalidTeamMemberSkipped),
184 "ATM_WARNING_MAILBOX_RECORD_SKIPPED" => Ok(Self::WarningMailboxRecordSkipped),
185 "ATM_WARNING_MALFORMED_ATM_FIELD_IGNORED" => Ok(Self::WarningMalformedAtmFieldIgnored),
186 "ATM_WARNING_OBSERVABILITY_HEALTH_DEGRADED" => {
187 Ok(Self::WarningObservabilityHealthDegraded)
188 }
189 "ATM_WARNING_ORIGIN_INBOX_ENTRY_SKIPPED" => Ok(Self::WarningOriginInboxEntrySkipped),
190 "ATM_WARNING_MISSING_TEAM_CONFIG_FALLBACK" => {
191 Ok(Self::WarningMissingTeamConfigFallback)
192 }
193 "ATM_WARNING_SEND_ALERT_STATE_DEGRADED" => Ok(Self::WarningSendAlertStateDegraded),
194 "ATM_WARNING_IDENTITY_DRIFT" => Ok(Self::WarningIdentityDrift),
195 "ATM_WARNING_BASELINE_MEMBER_MISSING" => Ok(Self::WarningBaselineMemberMissing),
196 "ATM_WARNING_RESTORE_IN_PROGRESS" => Ok(Self::WarningRestoreInProgress),
197 "ATM_WARNING_STALE_MAILBOX_LOCK" => Ok(Self::WarningStaleMailboxLock),
198 "ATM_WARNING_HOOK_SKIPPED" => Ok(Self::WarningHookSkipped),
199 "ATM_WARNING_HOOK_EXECUTION_FAILED" => Ok(Self::WarningHookExecutionFailed),
200 _ => Err("unknown ATM error code"),
201 }
202 }
203}
204
205impl fmt::Display for AtmErrorCode {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 f.write_str(self.as_str())
208 }
209}
210
211impl Serialize for AtmErrorCode {
212 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
213 where
214 S: serde::Serializer,
215 {
216 serializer.serialize_str(self.as_str())
217 }
218}
219
220impl<'de> Deserialize<'de> for AtmErrorCode {
221 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222 where
223 D: Deserializer<'de>,
224 {
225 let value = String::deserialize(deserializer)?;
226 value.parse().map_err(serde::de::Error::custom)
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::AtmErrorCode;
233
234 #[test]
235 fn error_code_round_trips_through_json_string() {
236 let encoded =
237 serde_json::to_string(&AtmErrorCode::MailboxLockReadOnlyFilesystem).expect("serialize");
238 assert_eq!(encoded, "\"ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM\"");
239
240 let decoded: AtmErrorCode = serde_json::from_str(&encoded).expect("deserialize");
241 assert_eq!(decoded, AtmErrorCode::MailboxLockReadOnlyFilesystem);
242 }
243}