Skip to main content

cairn_cli/
errors.rs

1use thiserror::Error;
2
3/// All 16 exit codes from the Cairn CLI specification.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum ExitCodeKind {
6    Success = 0,
7    GeneralError = 1,
8    InvalidInput = 2,
9    AuthError = 3,
10    NotFound = 4,
11    Conflict = 5,
12    IntentExpired = 6,
13    IntentAborted = 7,
14    ChainDepthExceeded = 8,
15    Timeout = 9,
16    SignatureError = 10,
17    PotNotReady = 11,
18    NetworkError = 12,
19    TokenExpired = 13,
20    ChallengeExpired = 14,
21    InsufficientFunds = 15,
22}
23
24#[derive(Debug, Error)]
25pub enum CairnError {
26    #[error("General error: {0}")]
27    General(String),
28
29    #[error("Invalid input: {0}")]
30    InvalidInput(String),
31
32    #[error("Authentication error: {0}")]
33    Auth(String),
34
35    #[error("Resource not found: {0}")]
36    NotFound(String),
37
38    #[error("Conflict: {0}")]
39    Conflict(String),
40
41    #[error("Intent expired: {0}")]
42    IntentExpired(String),
43
44    #[error("Intent aborted: {0}")]
45    IntentAborted(String),
46
47    #[error("Chain depth exceeded")]
48    ChainDepthExceeded,
49
50    #[error("Operation timed out")]
51    Timeout,
52
53    #[error("Signature verification failed: {0}")]
54    SignatureError(String),
55
56    #[error("Proof of Transport not ready")]
57    PotNotReady,
58
59    #[error("Network error: {0}")]
60    Network(String),
61
62    #[error("Token expired")]
63    TokenExpired,
64
65    #[error("Challenge expired")]
66    ChallengeExpired,
67
68    #[error("Insufficient funds: {0}")]
69    InsufficientFunds(String),
70}
71
72impl CairnError {
73    pub fn exit_code(&self) -> u8 {
74        match self {
75            Self::General(_) => ExitCodeKind::GeneralError as u8,
76            Self::InvalidInput(_) => ExitCodeKind::InvalidInput as u8,
77            Self::Auth(_) => ExitCodeKind::AuthError as u8,
78            Self::NotFound(_) => ExitCodeKind::NotFound as u8,
79            Self::Conflict(_) => ExitCodeKind::Conflict as u8,
80            Self::IntentExpired(_) => ExitCodeKind::IntentExpired as u8,
81            Self::IntentAborted(_) => ExitCodeKind::IntentAborted as u8,
82            Self::ChainDepthExceeded => ExitCodeKind::ChainDepthExceeded as u8,
83            Self::Timeout => ExitCodeKind::Timeout as u8,
84            Self::SignatureError(_) => ExitCodeKind::SignatureError as u8,
85            Self::PotNotReady => ExitCodeKind::PotNotReady as u8,
86            Self::Network(_) => ExitCodeKind::NetworkError as u8,
87            Self::TokenExpired => ExitCodeKind::TokenExpired as u8,
88            Self::ChallengeExpired => ExitCodeKind::ChallengeExpired as u8,
89            Self::InsufficientFunds(_) => ExitCodeKind::InsufficientFunds as u8,
90        }
91    }
92}
93
94impl From<reqwest::Error> for CairnError {
95    fn from(e: reqwest::Error) -> Self {
96        CairnError::Network(e.to_string())
97    }
98}
99
100impl From<serde_json::Error> for CairnError {
101    fn from(e: serde_json::Error) -> Self {
102        CairnError::General(format!("JSON error: {}", e))
103    }
104}
105
106impl From<std::io::Error> for CairnError {
107    fn from(e: std::io::Error) -> Self {
108        CairnError::General(format!("IO error: {}", e))
109    }
110}