Skip to main content

scosh_core/
errors.rs

1//! Stable error categories for host adapters.
2
3use std::fmt;
4
5/// Host-visible category. Details stay in the adapter and are never part of
6/// the mobile API contract.
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum ErrorCategory {
9    Authentication,
10    HostVerification,
11    Capability,
12    Protocol,
13    Transport,
14    Recovery,
15    Cancelled,
16    SessionClosed,
17    ConsumerStalled,
18    Worker,
19}
20
21impl fmt::Display for ErrorCategory {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        f.write_str(match self {
24            Self::Authentication => "authentication",
25            Self::HostVerification => "host-verification",
26            Self::Capability => "capability",
27            Self::Protocol => "protocol",
28            Self::Transport => "transport",
29            Self::Recovery => "recovery",
30            Self::Cancelled => "cancelled",
31            Self::SessionClosed => "session-closed",
32            Self::ConsumerStalled => "consumer-stalled",
33            Self::Worker => "worker",
34        })
35    }
36}
37
38/// Category plus a stable reason, without propagating adapter error strings.
39#[derive(Clone, Copy, Debug, Eq, PartialEq)]
40pub enum SdkError {
41    Authentication,
42    HostKeyRejected,
43    CapabilityRejected,
44    CapabilityExpired,
45    CapabilityReplayed,
46    CapabilityBindingMismatch,
47    ProtocolMismatch,
48    TransportUnavailable,
49    RecoveryExhausted,
50    Cancelled,
51    SessionClosed,
52    ConsumerStalled,
53    WorkerFailed,
54}
55
56impl SdkError {
57    pub const fn category(self) -> ErrorCategory {
58        match self {
59            Self::Authentication => ErrorCategory::Authentication,
60            Self::HostKeyRejected => ErrorCategory::HostVerification,
61            Self::CapabilityRejected
62            | Self::CapabilityExpired
63            | Self::CapabilityReplayed
64            | Self::CapabilityBindingMismatch => ErrorCategory::Capability,
65            Self::ProtocolMismatch => ErrorCategory::Protocol,
66            Self::TransportUnavailable => ErrorCategory::Transport,
67            Self::RecoveryExhausted => ErrorCategory::Recovery,
68            Self::Cancelled => ErrorCategory::Cancelled,
69            Self::SessionClosed => ErrorCategory::SessionClosed,
70            Self::ConsumerStalled => ErrorCategory::ConsumerStalled,
71            Self::WorkerFailed => ErrorCategory::Worker,
72        }
73    }
74}
75
76impl fmt::Display for SdkError {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        f.write_str(match self {
79            Self::Authentication => "authentication failed",
80            Self::HostKeyRejected => "host verification failed",
81            Self::CapabilityRejected => "bootstrap capability rejected",
82            Self::CapabilityExpired => "bootstrap capability expired",
83            Self::CapabilityReplayed => "bootstrap capability was already consumed",
84            Self::CapabilityBindingMismatch => "bootstrap capability binding mismatch",
85            Self::ProtocolMismatch => "protocol version mismatch",
86            Self::TransportUnavailable => "transport unavailable",
87            Self::RecoveryExhausted => "recovery budget exhausted",
88            Self::Cancelled => "operation cancelled",
89            Self::SessionClosed => "session is closed",
90            Self::ConsumerStalled => "host consumer stalled",
91            Self::WorkerFailed => "session worker failed",
92        })
93    }
94}
95
96impl std::error::Error for SdkError {}