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