Skip to main content

tokilake_core/
error.rs

1use thiserror::Error;
2
3/// Tunnel error types.
4#[derive(Debug, Error)]
5pub enum TunnelError {
6    #[error("stream closed")]
7    StreamClosed,
8
9    #[error("connection timeout")]
10    Timeout,
11
12    #[error("authentication failed: {message}")]
13    AuthFailed { message: String },
14
15    #[error("protocol error: {message}")]
16    Protocol { message: String },
17
18    #[error("transport error: {0}")]
19    Transport(#[from] std::io::Error),
20
21    #[error("serialization error: {0}")]
22    Serialization(#[from] serde_json::Error),
23
24    #[error("session offline")]
25    SessionOffline,
26
27    #[error("{0}")]
28    Other(#[from] anyhow::Error),
29}
30
31impl TunnelError {
32    pub fn auth_failed(message: impl Into<String>) -> Self {
33        Self::AuthFailed {
34            message: message.into(),
35        }
36    }
37
38    pub fn protocol(message: impl Into<String>) -> Self {
39        Self::Protocol {
40            message: message.into(),
41        }
42    }
43}
44
45/// Error message for control protocol.
46#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
47pub struct ErrorMessage {
48    #[serde(skip_serializing_if = "String::is_empty", default)]
49    pub code:    String,
50    pub message: String,
51}
52
53impl ErrorMessage {
54    pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
55        Self {
56            code:    code.into(),
57            message: message.into(),
58        }
59    }
60}
61
62impl std::fmt::Display for ErrorMessage {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        if self.code.is_empty() {
65            write!(f, "{}", self.message)
66        } else {
67            write!(f, "[{}] {}", self.code, self.message)
68        }
69    }
70}
71
72/// Helper trait to map errors to TunnelError.
73pub trait MapTunnelErr<T> {
74    /// Maps any error to TunnelError::StreamClosed.
75    fn map_stream_closed(self) -> Result<T, TunnelError>;
76}
77
78impl<T, E> MapTunnelErr<T> for Result<T, E> {
79    fn map_stream_closed(self) -> Result<T, TunnelError> {
80        self.map_err(|_| TunnelError::StreamClosed)
81    }
82}