Skip to main content

atm_storage/
error_codes.rs

1//! Stable ATM-owned error-code registry.
2
3use std::fmt;
4use std::str::FromStr;
5
6use serde::{Deserialize, Deserializer, Serialize};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct UnknownAtmErrorCode(pub String);
10
11impl fmt::Display for UnknownAtmErrorCode {
12    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13        write!(f, "unknown ATM error code: {}", self.0)
14    }
15}
16
17impl std::error::Error for UnknownAtmErrorCode {}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub enum AtmErrorCode {
21    ConfigHomeUnavailable,
22    ConfigParseFailed,
23    ConfigRetiredHookMembersKey,
24    ConfigRetiredLegacyHookKeys,
25    ConfigTeamParseFailed,
26    ConfigTeamMissing,
27    IdentityUnavailable,
28    IdentityConflict,
29    DaemonUnavailable,
30    DaemonMayHaveExecuted,
31    DaemonLifecycleWedge,
32    DaemonLaunchGateRejected,
33    DaemonServingStateRejected,
34    DaemonStaleOwnerRecoveryFailed,
35    DaemonAutoStartFailed,
36    DaemonAdvisorySessionAlreadyRegistered,
37    DaemonAdvisorySessionNotRegistered,
38    RemoteDeliveryOutcomeUnknown,
39    AddressParseFailed,
40    TeamUnavailable,
41    TeamNotFound,
42    AgentNotFound,
43    MailboxReadFailed,
44    MailboxRecoveredMessageSetTooLarge,
45    MailboxWriteFailed,
46    MailboxLockFailed,
47    MailboxLockReadOnlyFilesystem,
48    MailboxLockTimeout,
49    InternalError,
50    MessageValidationFailed,
51    SerializationFailed,
52    FilePolicyRejected,
53    FileReferenceRewriteFailed,
54    WaitTimeout,
55    AckInvalidState,
56    ClearInvalidState,
57    ObservabilityEmitFailed,
58    ObservabilityQueryFailed,
59    ObservabilityFollowFailed,
60    ObservabilityHealthFailed,
61    ObservabilityBootstrapFailed,
62    ObservabilityHealthOk,
63    WarningInvalidTeamMemberSkipped,
64    WarningMailboxRecordSkipped,
65    WarningMalformedAtmFieldIgnored,
66    WarningObservabilityHealthDegraded,
67    WarningSqliteHealthDegraded,
68    WarningOriginInboxEntrySkipped,
69    WarningMissingTeamConfigFallback,
70    WarningSendAlertStateDegraded,
71    WarningIdentityDrift,
72    WarningRosterDrift,
73    WarningBaselineMemberMissing,
74    WarningRestoreInProgress,
75    WarningStaleMailboxLock,
76    WarningHookSkipped,
77    WarningHookExecutionFailed,
78    TestFakeTransportInjectionFailed,
79    HelpTopicNotFound,
80}
81
82impl AtmErrorCode {
83    pub const fn as_str(self) -> &'static str {
84        match self {
85            Self::ConfigHomeUnavailable => "ATM_CONFIG_HOME_UNAVAILABLE",
86            Self::ConfigParseFailed => "ATM_CONFIG_PARSE_FAILED",
87            Self::ConfigRetiredHookMembersKey => "ATM_CONFIG_RETIRED_HOOK_MEMBERS_KEY",
88            Self::ConfigRetiredLegacyHookKeys => "ATM_CONFIG_RETIRED_LEGACY_HOOK_KEYS",
89            Self::ConfigTeamParseFailed => "ATM_CONFIG_TEAM_PARSE_FAILED",
90            Self::ConfigTeamMissing => "ATM_CONFIG_TEAM_MISSING",
91            Self::IdentityUnavailable => "ATM_IDENTITY_UNAVAILABLE",
92            Self::IdentityConflict => "ATM_IDENTITY_CONFLICT",
93            Self::DaemonUnavailable => "ATM_DAEMON_UNAVAILABLE",
94            Self::DaemonMayHaveExecuted => "ATM_DAEMON_MAY_HAVE_EXECUTED",
95            Self::DaemonLifecycleWedge => "ATM_DAEMON_LIFECYCLE_WEDGE",
96            Self::DaemonLaunchGateRejected => "ATM_DAEMON_LAUNCH_GATE_REJECTED",
97            Self::DaemonServingStateRejected => "ATM_DAEMON_SERVING_STATE_REJECTED",
98            Self::DaemonStaleOwnerRecoveryFailed => "ATM_DAEMON_STALE_OWNER_RECOVERY_FAILED",
99            Self::DaemonAutoStartFailed => "ATM_DAEMON_AUTO_START_FAILED",
100            Self::DaemonAdvisorySessionAlreadyRegistered => {
101                "ATM_DAEMON_ADVISORY_SESSION_ALREADY_REGISTERED"
102            }
103            Self::DaemonAdvisorySessionNotRegistered => {
104                "ATM_DAEMON_ADVISORY_SESSION_NOT_REGISTERED"
105            }
106            Self::RemoteDeliveryOutcomeUnknown => "ATM_REMOTE_OUTCOME_UNKNOWN",
107            Self::AddressParseFailed => "ATM_ADDRESS_PARSE_FAILED",
108            Self::TeamUnavailable => "ATM_TEAM_UNAVAILABLE",
109            Self::TeamNotFound => "ATM_TEAM_NOT_FOUND",
110            Self::AgentNotFound => "ATM_AGENT_NOT_FOUND",
111            Self::MailboxReadFailed => "ATM_MAILBOX_READ_FAILED",
112            Self::MailboxRecoveredMessageSetTooLarge => {
113                "ATM_MAILBOX_RECOVERED_MESSAGE_SET_TOO_LARGE"
114            }
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::InternalError => "ATM_INTERNAL_ERROR",
120            Self::MessageValidationFailed => "ATM_MESSAGE_VALIDATION_FAILED",
121            Self::SerializationFailed => "ATM_SERIALIZATION_FAILED",
122            Self::FilePolicyRejected => "ATM_FILE_POLICY_REJECTED",
123            Self::FileReferenceRewriteFailed => "ATM_FILE_REFERENCE_REWRITE_FAILED",
124            Self::WaitTimeout => "ATM_WAIT_TIMEOUT",
125            Self::AckInvalidState => "ATM_ACK_INVALID_STATE",
126            Self::ClearInvalidState => "ATM_CLEAR_INVALID_STATE",
127            Self::ObservabilityEmitFailed => "ATM_OBSERVABILITY_EMIT_FAILED",
128            Self::ObservabilityQueryFailed => "ATM_OBSERVABILITY_QUERY_FAILED",
129            Self::ObservabilityFollowFailed => "ATM_OBSERVABILITY_FOLLOW_FAILED",
130            Self::ObservabilityHealthFailed => "ATM_OBSERVABILITY_HEALTH_FAILED",
131            Self::ObservabilityBootstrapFailed => "ATM_OBSERVABILITY_BOOTSTRAP_FAILED",
132            Self::ObservabilityHealthOk => "ATM_OBSERVABILITY_HEALTH_OK",
133            Self::WarningInvalidTeamMemberSkipped => "ATM_WARNING_INVALID_TEAM_MEMBER_SKIPPED",
134            Self::WarningMailboxRecordSkipped => "ATM_WARNING_MAILBOX_RECORD_SKIPPED",
135            Self::WarningMalformedAtmFieldIgnored => "ATM_WARNING_MALFORMED_ATM_FIELD_IGNORED",
136            Self::WarningObservabilityHealthDegraded => "ATM_WARNING_OBSERVABILITY_HEALTH_DEGRADED",
137            Self::WarningSqliteHealthDegraded => "ATM_WARNING_SQLITE_HEALTH_DEGRADED",
138            Self::WarningOriginInboxEntrySkipped => "ATM_WARNING_ORIGIN_INBOX_ENTRY_SKIPPED",
139            Self::WarningMissingTeamConfigFallback => "ATM_WARNING_MISSING_TEAM_CONFIG_FALLBACK",
140            Self::WarningSendAlertStateDegraded => "ATM_WARNING_SEND_ALERT_STATE_DEGRADED",
141            Self::WarningIdentityDrift => "ATM_WARNING_IDENTITY_DRIFT",
142            Self::WarningRosterDrift => "ATM_WARNING_ROSTER_DRIFT",
143            Self::WarningBaselineMemberMissing => "ATM_WARNING_BASELINE_MEMBER_MISSING",
144            Self::WarningRestoreInProgress => "ATM_WARNING_RESTORE_IN_PROGRESS",
145            Self::WarningStaleMailboxLock => "ATM_WARNING_STALE_MAILBOX_LOCK",
146            Self::WarningHookSkipped => "ATM_WARNING_HOOK_SKIPPED",
147            Self::WarningHookExecutionFailed => "ATM_WARNING_HOOK_EXECUTION_FAILED",
148            Self::TestFakeTransportInjectionFailed => "ATM_TEST_FAKE_TRANSPORT_INJECTION_FAILED",
149            Self::HelpTopicNotFound => "ATM_HELP_TOPIC_NOT_FOUND",
150        }
151    }
152}
153
154impl FromStr for AtmErrorCode {
155    type Err = UnknownAtmErrorCode;
156
157    fn from_str(value: &str) -> Result<Self, Self::Err> {
158        match value {
159            "ATM_CONFIG_HOME_UNAVAILABLE" => Ok(Self::ConfigHomeUnavailable),
160            "ATM_CONFIG_PARSE_FAILED" => Ok(Self::ConfigParseFailed),
161            "ATM_CONFIG_RETIRED_HOOK_MEMBERS_KEY" => Ok(Self::ConfigRetiredHookMembersKey),
162            "ATM_CONFIG_RETIRED_LEGACY_HOOK_KEYS" => Ok(Self::ConfigRetiredLegacyHookKeys),
163            "ATM_CONFIG_TEAM_PARSE_FAILED" => Ok(Self::ConfigTeamParseFailed),
164            "ATM_CONFIG_TEAM_MISSING" => Ok(Self::ConfigTeamMissing),
165            "ATM_IDENTITY_UNAVAILABLE" => Ok(Self::IdentityUnavailable),
166            "ATM_IDENTITY_CONFLICT" => Ok(Self::IdentityConflict),
167            "ATM_DAEMON_UNAVAILABLE" => Ok(Self::DaemonUnavailable),
168            "ATM_DAEMON_MAY_HAVE_EXECUTED" => Ok(Self::DaemonMayHaveExecuted),
169            "ATM_DAEMON_LIFECYCLE_WEDGE" => Ok(Self::DaemonLifecycleWedge),
170            "ATM_DAEMON_LAUNCH_GATE_REJECTED" => Ok(Self::DaemonLaunchGateRejected),
171            "ATM_DAEMON_SERVING_STATE_REJECTED" => Ok(Self::DaemonServingStateRejected),
172            "ATM_DAEMON_STALE_OWNER_RECOVERY_FAILED" => Ok(Self::DaemonStaleOwnerRecoveryFailed),
173            "ATM_DAEMON_AUTO_START_FAILED" => Ok(Self::DaemonAutoStartFailed),
174            "ATM_DAEMON_ADVISORY_SESSION_ALREADY_REGISTERED" => {
175                Ok(Self::DaemonAdvisorySessionAlreadyRegistered)
176            }
177            "ATM_DAEMON_ADVISORY_SESSION_NOT_REGISTERED" => {
178                Ok(Self::DaemonAdvisorySessionNotRegistered)
179            }
180            "ATM_REMOTE_OUTCOME_UNKNOWN" => Ok(Self::RemoteDeliveryOutcomeUnknown),
181            "ATM_ADDRESS_PARSE_FAILED" => Ok(Self::AddressParseFailed),
182            "ATM_TEAM_UNAVAILABLE" => Ok(Self::TeamUnavailable),
183            "ATM_TEAM_NOT_FOUND" => Ok(Self::TeamNotFound),
184            "ATM_AGENT_NOT_FOUND" => Ok(Self::AgentNotFound),
185            "ATM_MAILBOX_READ_FAILED" => Ok(Self::MailboxReadFailed),
186            "ATM_MAILBOX_RECOVERED_MESSAGE_SET_TOO_LARGE" => {
187                Ok(Self::MailboxRecoveredMessageSetTooLarge)
188            }
189            "ATM_MAILBOX_WRITE_FAILED" => Ok(Self::MailboxWriteFailed),
190            "ATM_MAILBOX_LOCK_FAILED" => Ok(Self::MailboxLockFailed),
191            "ATM_MAILBOX_LOCK_READ_ONLY_FILESYSTEM" => Ok(Self::MailboxLockReadOnlyFilesystem),
192            "ATM_MAILBOX_LOCK_TIMEOUT" => Ok(Self::MailboxLockTimeout),
193            "ATM_INTERNAL_ERROR" => Ok(Self::InternalError),
194            "ATM_MESSAGE_VALIDATION_FAILED" => Ok(Self::MessageValidationFailed),
195            "ATM_SERIALIZATION_FAILED" => Ok(Self::SerializationFailed),
196            "ATM_FILE_POLICY_REJECTED" => Ok(Self::FilePolicyRejected),
197            "ATM_FILE_REFERENCE_REWRITE_FAILED" => Ok(Self::FileReferenceRewriteFailed),
198            "ATM_WAIT_TIMEOUT" => Ok(Self::WaitTimeout),
199            "ATM_ACK_INVALID_STATE" => Ok(Self::AckInvalidState),
200            "ATM_CLEAR_INVALID_STATE" => Ok(Self::ClearInvalidState),
201            "ATM_OBSERVABILITY_EMIT_FAILED" => Ok(Self::ObservabilityEmitFailed),
202            "ATM_OBSERVABILITY_QUERY_FAILED" => Ok(Self::ObservabilityQueryFailed),
203            "ATM_OBSERVABILITY_FOLLOW_FAILED" => Ok(Self::ObservabilityFollowFailed),
204            "ATM_OBSERVABILITY_HEALTH_FAILED" => Ok(Self::ObservabilityHealthFailed),
205            "ATM_OBSERVABILITY_BOOTSTRAP_FAILED" => Ok(Self::ObservabilityBootstrapFailed),
206            "ATM_OBSERVABILITY_HEALTH_OK" => Ok(Self::ObservabilityHealthOk),
207            "ATM_WARNING_INVALID_TEAM_MEMBER_SKIPPED" => Ok(Self::WarningInvalidTeamMemberSkipped),
208            "ATM_WARNING_MAILBOX_RECORD_SKIPPED" => Ok(Self::WarningMailboxRecordSkipped),
209            "ATM_WARNING_MALFORMED_ATM_FIELD_IGNORED" => Ok(Self::WarningMalformedAtmFieldIgnored),
210            "ATM_WARNING_OBSERVABILITY_HEALTH_DEGRADED" => {
211                Ok(Self::WarningObservabilityHealthDegraded)
212            }
213            "ATM_WARNING_SQLITE_HEALTH_DEGRADED" => Ok(Self::WarningSqliteHealthDegraded),
214            "ATM_WARNING_ORIGIN_INBOX_ENTRY_SKIPPED" => Ok(Self::WarningOriginInboxEntrySkipped),
215            "ATM_WARNING_MISSING_TEAM_CONFIG_FALLBACK" => {
216                Ok(Self::WarningMissingTeamConfigFallback)
217            }
218            "ATM_WARNING_SEND_ALERT_STATE_DEGRADED" => Ok(Self::WarningSendAlertStateDegraded),
219            "ATM_WARNING_IDENTITY_DRIFT" => Ok(Self::WarningIdentityDrift),
220            "ATM_WARNING_ROSTER_DRIFT" => Ok(Self::WarningRosterDrift),
221            "ATM_WARNING_BASELINE_MEMBER_MISSING" => Ok(Self::WarningBaselineMemberMissing),
222            "ATM_WARNING_RESTORE_IN_PROGRESS" => Ok(Self::WarningRestoreInProgress),
223            "ATM_WARNING_STALE_MAILBOX_LOCK" => Ok(Self::WarningStaleMailboxLock),
224            "ATM_WARNING_HOOK_SKIPPED" => Ok(Self::WarningHookSkipped),
225            "ATM_WARNING_HOOK_EXECUTION_FAILED" => Ok(Self::WarningHookExecutionFailed),
226            "ATM_TEST_FAKE_TRANSPORT_INJECTION_FAILED" => {
227                Ok(Self::TestFakeTransportInjectionFailed)
228            }
229            "ATM_HELP_TOPIC_NOT_FOUND" => Ok(Self::HelpTopicNotFound),
230            _ => Err(UnknownAtmErrorCode(value.to_owned())),
231        }
232    }
233}
234
235impl fmt::Display for AtmErrorCode {
236    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237        f.write_str(self.as_str())
238    }
239}
240
241impl Serialize for AtmErrorCode {
242    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243    where
244        S: serde::Serializer,
245    {
246        serializer.serialize_str(self.as_str())
247    }
248}
249
250impl<'de> Deserialize<'de> for AtmErrorCode {
251    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
252    where
253        D: Deserializer<'de>,
254    {
255        let value = String::deserialize(deserializer)?;
256        value.parse().map_err(serde::de::Error::custom)
257    }
258}