Skip to main content

clasp_core/
error.rs

1//! Error types for Clasp
2
3use thiserror::Error;
4
5/// Result type alias for Clasp operations
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Clasp error types
9#[derive(Error, Debug)]
10pub enum Error {
11    /// Invalid magic byte in frame header
12    #[error("invalid magic byte: expected 0x53, got 0x{0:02x}")]
13    InvalidMagic(u8),
14
15    /// Frame payload too large
16    #[error("payload too large: {0} bytes (max 65535)")]
17    PayloadTooLarge(usize),
18
19    /// Frame buffer too small
20    #[error("buffer too small: need {needed} bytes, have {have}")]
21    BufferTooSmall { needed: usize, have: usize },
22
23    /// MessagePack encoding error
24    #[error("encode error: {0}")]
25    EncodeError(String),
26
27    /// MessagePack decoding error
28    #[error("decode error: {0}")]
29    DecodeError(String),
30
31    /// Invalid message type code
32    #[error("unknown message type: 0x{0:02x}")]
33    UnknownMessageType(u8),
34
35    /// Invalid signal type
36    #[error("unknown signal type: {0}")]
37    UnknownSignalType(String),
38
39    /// Invalid address format
40    #[error("invalid address: {0}")]
41    InvalidAddress(String),
42
43    /// Address pattern compilation error
44    #[error("invalid pattern: {0}")]
45    InvalidPattern(String),
46
47    /// State conflict
48    #[error("state conflict: revision {expected} expected, got {actual}")]
49    RevisionConflict { expected: u64, actual: u64 },
50
51    /// Lock held by another session
52    #[error("lock held by {holder}")]
53    LockHeld { holder: String },
54
55    /// Permission denied
56    #[error("permission denied: {0}")]
57    PermissionDenied(String),
58
59    /// Connection error
60    #[error("connection error: {0}")]
61    ConnectionError(String),
62
63    /// Timeout
64    #[error("operation timed out")]
65    Timeout,
66
67    /// Generic protocol error
68    #[error("protocol error: {0}")]
69    Protocol(String),
70}
71
72impl From<rmp_serde::encode::Error> for Error {
73    fn from(e: rmp_serde::encode::Error) -> Self {
74        Error::EncodeError(e.to_string())
75    }
76}
77
78impl From<rmp_serde::decode::Error> for Error {
79    fn from(e: rmp_serde::decode::Error) -> Self {
80        Error::DecodeError(e.to_string())
81    }
82}
83
84/// Protocol error codes (for ERROR messages)
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86#[repr(u16)]
87pub enum ErrorCode {
88    // 100-199: Protocol errors
89    InvalidFrame = 100,
90    InvalidMessage = 101,
91    UnsupportedVersion = 102,
92
93    // 200-299: Address errors
94    InvalidAddress = 200,
95    AddressNotFound = 201,
96    PatternError = 202,
97
98    // 300-399: Permission errors
99    Unauthorized = 300,
100    Forbidden = 301,
101    TokenExpired = 302,
102
103    // 400-499: State errors
104    RevisionConflict = 400,
105    LockHeld = 401,
106    InvalidValue = 402,
107
108    // 500-599: Server errors
109    InternalError = 500,
110    ServiceUnavailable = 501,
111    Timeout = 502,
112}
113
114impl ErrorCode {
115    pub fn from_u16(code: u16) -> Option<Self> {
116        match code {
117            100 => Some(ErrorCode::InvalidFrame),
118            101 => Some(ErrorCode::InvalidMessage),
119            102 => Some(ErrorCode::UnsupportedVersion),
120            200 => Some(ErrorCode::InvalidAddress),
121            201 => Some(ErrorCode::AddressNotFound),
122            202 => Some(ErrorCode::PatternError),
123            300 => Some(ErrorCode::Unauthorized),
124            301 => Some(ErrorCode::Forbidden),
125            302 => Some(ErrorCode::TokenExpired),
126            400 => Some(ErrorCode::RevisionConflict),
127            401 => Some(ErrorCode::LockHeld),
128            402 => Some(ErrorCode::InvalidValue),
129            500 => Some(ErrorCode::InternalError),
130            501 => Some(ErrorCode::ServiceUnavailable),
131            502 => Some(ErrorCode::Timeout),
132            _ => None,
133        }
134    }
135}