tramex_tools/
errors.rs

1//! Error handling for Tramex Tools
2
3#[derive(Default, serde::Deserialize, Debug, Clone)]
4/// Error codes for Tramex Tools
5pub enum ErrorCode {
6    /// Not set
7    #[default]
8    NotSet = 0,
9
10    /// WebSocket: Failed to connect
11    WebSocketFailedToConnect,
12
13    /// WebSocket: Error encoding message
14    WebSocketErrorEncodingMessage,
15
16    /// WebSocket: Error decoding message
17    WebSocketErrorDecodingMessage,
18
19    /// WebSocket: Unknown message received
20    WebSocketUnknownMessageReceived,
21
22    /// WebSocket: Unknown binary message received
23    WebSocketUnknownBinaryMessageReceived,
24
25    /// WebSocket: Error
26    WebSocketError,
27
28    /// WebSocket: Closed
29    WebSocketClosed,
30
31    /// WebSocket: Error closing
32    WebSocketErrorClosing,
33
34    /// File: No file selected
35    FileNotSelected,
36
37    /// File: Error reading file
38    FileErrorReadingFile,
39
40    /// File: Not ready
41    FileNotReady,
42
43    /// File: Invalid encoding (wrong UTF-8)
44    FileInvalidEncoding,
45
46    /// Hexe decoding failed
47    HexeDecodingError,
48
49    /// File : End of the file
50    EndOfFile,
51
52    /// File: Error while parsing the file
53    FileParsing,
54
55    /// Request error
56    RequestError,
57
58    /// ParsingLayerNotImplemented
59    ParsingLayerNotImplemented,
60}
61
62impl std::fmt::Display for ErrorCode {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        // use to_string() to get the string representation of the error code
65        let str = match self {
66            Self::WebSocketFailedToConnect => "WebSocket: Failed to connect",
67            Self::WebSocketErrorEncodingMessage => "WebSocket: Error encoding message",
68            Self::WebSocketErrorDecodingMessage => "WebSocket: Error decoding message",
69            Self::WebSocketUnknownMessageReceived => "WebSocket: Unknown message received",
70            Self::WebSocketUnknownBinaryMessageReceived => "WebSocket: Unknown binary message received",
71            Self::WebSocketError => "WebSocket: Error",
72            Self::WebSocketClosed => "WebSocket: Closed",
73            Self::WebSocketErrorClosing => "WebSocket: Error closing",
74            Self::FileNotSelected => "File: No file selected",
75            Self::FileErrorReadingFile => "File: Error reading file",
76            Self::FileNotReady => "File: Not ready",
77            Self::FileInvalidEncoding => "File: Invalid encoding (wrong UTF-8)",
78            Self::NotSet => "Error code not set, please create an issue",
79            Self::HexeDecodingError => "Hexe decoding error",
80            Self::EndOfFile => "End of File",
81            Self::FileParsing => "File: Parsing error",
82            Self::RequestError => "Request error",
83            Self::ParsingLayerNotImplemented => "Parsing layer not implemented",
84        };
85        write!(f, "{str}")
86    }
87}
88
89impl ErrorCode {
90    /// Check if the error is recoverable
91    pub fn is_recoverable(&self) -> bool {
92        !matches!(self, Self::FileInvalidEncoding | Self::WebSocketClosed)
93    }
94}
95
96#[derive(serde::Deserialize, Debug, Default, Clone)]
97/// Error structure for Tramex Tools
98pub struct TramexError {
99    /// Error message (human readable)
100    pub message: String,
101
102    /// Debug information
103    pub debug: String,
104
105    /// Error code
106    code: ErrorCode,
107}
108
109impl TramexError {
110    /// Create a new error
111    pub fn new(message: String, code: ErrorCode) -> Self {
112        log::debug!("Error: {} - {}\n{}", code, message, std::backtrace::Backtrace::capture());
113        Self {
114            message,
115            code,
116            debug: String::new(),
117        }
118    }
119
120    /// Create a new error
121    pub fn new_with_line(message: String, code: ErrorCode, debug: String) -> Self {
122        Self { message, code, debug }
123    }
124
125    /// Check if the error is recoverable
126    pub fn is_recoverable(&self) -> bool {
127        self.code.is_recoverable()
128    }
129
130    /// Get the error message
131    pub fn get_msg(&self) -> String {
132        format!("[{}] {}", self.code, self.message)
133    }
134
135    /// Get the error code
136    pub fn get_code(&self) -> ErrorCode {
137        self.code.clone()
138    }
139}
140
141/// Macro to get the file and line number
142#[macro_export]
143macro_rules! tramex_error {
144    ($msg:expr, $code:expr) => {
145        TramexError::new_with_line($msg, $code, format!("{}:{}", file!(), line!()))
146    };
147}