Skip to main content

cairn_cli/
errors.rs

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