use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AtmErrorCode {
ConfigHomeUnavailable,
ConfigParseFailed,
ConfigRetiredHookMembersKey,
ConfigRetiredLegacyHookKeys,
ConfigTeamParseFailed,
ConfigTeamMissing,
IdentityUnavailable,
AddressParseFailed,
TeamUnavailable,
TeamNotFound,
AgentNotFound,
MailboxReadFailed,
MailboxWriteFailed,
MailboxLockFailed,
MailboxLockReadOnlyFilesystem,
MailboxLockTimeout,
MessageValidationFailed,
SerializationFailed,
FilePolicyRejected,
FileReferenceRewriteFailed,
WaitTimeout,
AckInvalidState,
ClearInvalidState,
ObservabilityEmitFailed,
ObservabilityQueryFailed,
ObservabilityFollowFailed,
ObservabilityHealthFailed,
ObservabilityBootstrapFailed,
ObservabilityHealthOk,
WarningInvalidTeamMemberSkipped,
WarningMailboxRecordSkipped,
WarningMalformedAtmFieldIgnored,
WarningObservabilityHealthDegraded,
WarningOriginInboxEntrySkipped,
WarningMissingTeamConfigFallback,
WarningSendAlertStateDegraded,
WarningIdentityDrift,
WarningBaselineMemberMissing,
WarningRestoreInProgress,
WarningStaleMailboxLock,
WarningHookSkipped,
WarningHookExecutionFailed,
}
impl AtmErrorCode {
pub const fn as_str(self) -> &'static str {
match self {
Self::ConfigHomeUnavailable => "ATM_CONFIG_HOME_UNAVAILABLE",
Self::ConfigParseFailed => "ATM_CONFIG_PARSE_FAILED",
Self::ConfigRetiredHookMembersKey => "ATM_CONFIG_RETIRED_HOOK_MEMBERS_KEY",
Self::ConfigRetiredLegacyHookKeys => "ATM_CONFIG_RETIRED_LEGACY_HOOK_KEYS",
Self::ConfigTeamParseFailed => "ATM_CONFIG_TEAM_PARSE_FAILED",
Self::ConfigTeamMissing => "ATM_CONFIG_TEAM_MISSING",
Self::IdentityUnavailable => "ATM_IDENTITY_UNAVAILABLE",
Self::AddressParseFailed => "ATM_ADDRESS_PARSE_FAILED",
Self::TeamUnavailable => "ATM_TEAM_UNAVAILABLE",
Self::TeamNotFound => "ATM_TEAM_NOT_FOUND",
Self::AgentNotFound => "ATM_AGENT_NOT_FOUND",
Self::MailboxReadFailed => "ATM_MAILBOX_READ_FAILED",
Self::MailboxWriteFailed => "ATM_MAILBOX_WRITE_FAILED",
Self::MailboxLockFailed => "ATM_MAILBOX_LOCK_FAILED",
Self::MailboxLockReadOnlyFilesystem => "ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM",
Self::MailboxLockTimeout => "ATM_MAILBOX_LOCK_TIMEOUT",
Self::MessageValidationFailed => "ATM_MESSAGE_VALIDATION_FAILED",
Self::SerializationFailed => "ATM_SERIALIZATION_FAILED",
Self::FilePolicyRejected => "ATM_FILE_POLICY_REJECTED",
Self::FileReferenceRewriteFailed => "ATM_FILE_REFERENCE_REWRITE_FAILED",
Self::WaitTimeout => "ATM_WAIT_TIMEOUT",
Self::AckInvalidState => "ATM_ACK_INVALID_STATE",
Self::ClearInvalidState => "ATM_CLEAR_INVALID_STATE",
Self::ObservabilityEmitFailed => "ATM_OBSERVABILITY_EMIT_FAILED",
Self::ObservabilityQueryFailed => "ATM_OBSERVABILITY_QUERY_FAILED",
Self::ObservabilityFollowFailed => "ATM_OBSERVABILITY_FOLLOW_FAILED",
Self::ObservabilityHealthFailed => "ATM_OBSERVABILITY_HEALTH_FAILED",
Self::ObservabilityBootstrapFailed => "ATM_OBSERVABILITY_BOOTSTRAP_FAILED",
Self::ObservabilityHealthOk => "ATM_OBSERVABILITY_HEALTH_OK",
Self::WarningInvalidTeamMemberSkipped => "ATM_WARNING_INVALID_TEAM_MEMBER_SKIPPED",
Self::WarningMailboxRecordSkipped => "ATM_WARNING_MAILBOX_RECORD_SKIPPED",
Self::WarningMalformedAtmFieldIgnored => "ATM_WARNING_MALFORMED_ATM_FIELD_IGNORED",
Self::WarningObservabilityHealthDegraded => "ATM_WARNING_OBSERVABILITY_HEALTH_DEGRADED",
Self::WarningOriginInboxEntrySkipped => "ATM_WARNING_ORIGIN_INBOX_ENTRY_SKIPPED",
Self::WarningMissingTeamConfigFallback => "ATM_WARNING_MISSING_TEAM_CONFIG_FALLBACK",
Self::WarningSendAlertStateDegraded => "ATM_WARNING_SEND_ALERT_STATE_DEGRADED",
Self::WarningIdentityDrift => "ATM_WARNING_IDENTITY_DRIFT",
Self::WarningBaselineMemberMissing => "ATM_WARNING_BASELINE_MEMBER_MISSING",
Self::WarningRestoreInProgress => "ATM_WARNING_RESTORE_IN_PROGRESS",
Self::WarningStaleMailboxLock => "ATM_WARNING_STALE_MAILBOX_LOCK",
Self::WarningHookSkipped => "ATM_WARNING_HOOK_SKIPPED",
Self::WarningHookExecutionFailed => "ATM_WARNING_HOOK_EXECUTION_FAILED",
}
}
}
impl FromStr for AtmErrorCode {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"ATM_CONFIG_HOME_UNAVAILABLE" => Ok(Self::ConfigHomeUnavailable),
"ATM_CONFIG_PARSE_FAILED" => Ok(Self::ConfigParseFailed),
"ATM_CONFIG_RETIRED_HOOK_MEMBERS_KEY" => Ok(Self::ConfigRetiredHookMembersKey),
"ATM_CONFIG_RETIRED_LEGACY_HOOK_KEYS" => Ok(Self::ConfigRetiredLegacyHookKeys),
"ATM_CONFIG_TEAM_PARSE_FAILED" => Ok(Self::ConfigTeamParseFailed),
"ATM_CONFIG_TEAM_MISSING" => Ok(Self::ConfigTeamMissing),
"ATM_IDENTITY_UNAVAILABLE" => Ok(Self::IdentityUnavailable),
"ATM_ADDRESS_PARSE_FAILED" => Ok(Self::AddressParseFailed),
"ATM_TEAM_UNAVAILABLE" => Ok(Self::TeamUnavailable),
"ATM_TEAM_NOT_FOUND" => Ok(Self::TeamNotFound),
"ATM_AGENT_NOT_FOUND" => Ok(Self::AgentNotFound),
"ATM_MAILBOX_READ_FAILED" => Ok(Self::MailboxReadFailed),
"ATM_MAILBOX_WRITE_FAILED" => Ok(Self::MailboxWriteFailed),
"ATM_MAILBOX_LOCK_FAILED" => Ok(Self::MailboxLockFailed),
"ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM" => Ok(Self::MailboxLockReadOnlyFilesystem),
"ATM_MAILBOX_LOCK_TIMEOUT" => Ok(Self::MailboxLockTimeout),
"ATM_MESSAGE_VALIDATION_FAILED" => Ok(Self::MessageValidationFailed),
"ATM_SERIALIZATION_FAILED" => Ok(Self::SerializationFailed),
"ATM_FILE_POLICY_REJECTED" => Ok(Self::FilePolicyRejected),
"ATM_FILE_REFERENCE_REWRITE_FAILED" => Ok(Self::FileReferenceRewriteFailed),
"ATM_WAIT_TIMEOUT" => Ok(Self::WaitTimeout),
"ATM_ACK_INVALID_STATE" => Ok(Self::AckInvalidState),
"ATM_CLEAR_INVALID_STATE" => Ok(Self::ClearInvalidState),
"ATM_OBSERVABILITY_EMIT_FAILED" => Ok(Self::ObservabilityEmitFailed),
"ATM_OBSERVABILITY_QUERY_FAILED" => Ok(Self::ObservabilityQueryFailed),
"ATM_OBSERVABILITY_FOLLOW_FAILED" => Ok(Self::ObservabilityFollowFailed),
"ATM_OBSERVABILITY_HEALTH_FAILED" => Ok(Self::ObservabilityHealthFailed),
"ATM_OBSERVABILITY_BOOTSTRAP_FAILED" => Ok(Self::ObservabilityBootstrapFailed),
"ATM_OBSERVABILITY_HEALTH_OK" => Ok(Self::ObservabilityHealthOk),
"ATM_WARNING_INVALID_TEAM_MEMBER_SKIPPED" => Ok(Self::WarningInvalidTeamMemberSkipped),
"ATM_WARNING_MAILBOX_RECORD_SKIPPED" => Ok(Self::WarningMailboxRecordSkipped),
"ATM_WARNING_MALFORMED_ATM_FIELD_IGNORED" => Ok(Self::WarningMalformedAtmFieldIgnored),
"ATM_WARNING_OBSERVABILITY_HEALTH_DEGRADED" => {
Ok(Self::WarningObservabilityHealthDegraded)
}
"ATM_WARNING_ORIGIN_INBOX_ENTRY_SKIPPED" => Ok(Self::WarningOriginInboxEntrySkipped),
"ATM_WARNING_MISSING_TEAM_CONFIG_FALLBACK" => {
Ok(Self::WarningMissingTeamConfigFallback)
}
"ATM_WARNING_SEND_ALERT_STATE_DEGRADED" => Ok(Self::WarningSendAlertStateDegraded),
"ATM_WARNING_IDENTITY_DRIFT" => Ok(Self::WarningIdentityDrift),
"ATM_WARNING_BASELINE_MEMBER_MISSING" => Ok(Self::WarningBaselineMemberMissing),
"ATM_WARNING_RESTORE_IN_PROGRESS" => Ok(Self::WarningRestoreInProgress),
"ATM_WARNING_STALE_MAILBOX_LOCK" => Ok(Self::WarningStaleMailboxLock),
"ATM_WARNING_HOOK_SKIPPED" => Ok(Self::WarningHookSkipped),
"ATM_WARNING_HOOK_EXECUTION_FAILED" => Ok(Self::WarningHookExecutionFailed),
_ => Err("unknown ATM error code"),
}
}
}
impl fmt::Display for AtmErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl Serialize for AtmErrorCode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for AtmErrorCode {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value = String::deserialize(deserializer)?;
value.parse().map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::AtmErrorCode;
#[test]
fn error_code_round_trips_through_json_string() {
let encoded =
serde_json::to_string(&AtmErrorCode::MailboxLockReadOnlyFilesystem).expect("serialize");
assert_eq!(encoded, "\"ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM\"");
let decoded: AtmErrorCode = serde_json::from_str(&encoded).expect("deserialize");
assert_eq!(decoded, AtmErrorCode::MailboxLockReadOnlyFilesystem);
}
}