scosh-core 0.1.0

Portable session state and terminal event core for scosh
Documentation
//! Stable error categories for host adapters.

use std::fmt;

/// Host-visible category. Details stay in the adapter and are never part of
/// the mobile API contract.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ErrorCategory {
    Authentication,
    HostVerification,
    Capability,
    Protocol,
    Transport,
    Recovery,
    Cancelled,
    SessionClosed,
    ConsumerStalled,
    Worker,
}

impl fmt::Display for ErrorCategory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Self::Authentication => "authentication",
            Self::HostVerification => "host-verification",
            Self::Capability => "capability",
            Self::Protocol => "protocol",
            Self::Transport => "transport",
            Self::Recovery => "recovery",
            Self::Cancelled => "cancelled",
            Self::SessionClosed => "session-closed",
            Self::ConsumerStalled => "consumer-stalled",
            Self::Worker => "worker",
        })
    }
}

/// Category plus a stable reason, without propagating adapter error strings.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SdkError {
    Authentication,
    HostKeyRejected,
    CapabilityRejected,
    CapabilityExpired,
    CapabilityReplayed,
    CapabilityBindingMismatch,
    ProtocolMismatch,
    TransportUnavailable,
    RecoveryExhausted,
    Cancelled,
    SessionClosed,
    ConsumerStalled,
    WorkerFailed,
}

impl SdkError {
    pub const fn category(self) -> ErrorCategory {
        match self {
            Self::Authentication => ErrorCategory::Authentication,
            Self::HostKeyRejected => ErrorCategory::HostVerification,
            Self::CapabilityRejected
            | Self::CapabilityExpired
            | Self::CapabilityReplayed
            | Self::CapabilityBindingMismatch => ErrorCategory::Capability,
            Self::ProtocolMismatch => ErrorCategory::Protocol,
            Self::TransportUnavailable => ErrorCategory::Transport,
            Self::RecoveryExhausted => ErrorCategory::Recovery,
            Self::Cancelled => ErrorCategory::Cancelled,
            Self::SessionClosed => ErrorCategory::SessionClosed,
            Self::ConsumerStalled => ErrorCategory::ConsumerStalled,
            Self::WorkerFailed => ErrorCategory::Worker,
        }
    }
}

impl fmt::Display for SdkError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Self::Authentication => "authentication failed",
            Self::HostKeyRejected => "host verification failed",
            Self::CapabilityRejected => "bootstrap capability rejected",
            Self::CapabilityExpired => "bootstrap capability expired",
            Self::CapabilityReplayed => "bootstrap capability was already consumed",
            Self::CapabilityBindingMismatch => "bootstrap capability binding mismatch",
            Self::ProtocolMismatch => "protocol version mismatch",
            Self::TransportUnavailable => "transport unavailable",
            Self::RecoveryExhausted => "recovery budget exhausted",
            Self::Cancelled => "operation cancelled",
            Self::SessionClosed => "session is closed",
            Self::ConsumerStalled => "host consumer stalled",
            Self::WorkerFailed => "session worker failed",
        })
    }
}

impl std::error::Error for SdkError {}