matrixcode_core/matrixrpc/protocol/
error.rs1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(transparent)]
12pub struct ErrorCode(pub i64);
13
14impl ErrorCode {
15 pub const PARSE_ERROR: Self = ErrorCode(-32700);
20
21 pub const INVALID_REQUEST: Self = ErrorCode(-32600);
23
24 pub const METHOD_NOT_FOUND: Self = ErrorCode(-32601);
26
27 pub const INVALID_PARAMS: Self = ErrorCode(-32602);
29
30 pub const INTERNAL_ERROR: Self = ErrorCode(-32603);
32
33 pub const SERVER_SHUTDOWN: Self = ErrorCode(-32000);
37
38 pub const TRANSPORT_ERROR: Self = ErrorCode(-32001);
40
41 pub const TIMEOUT_ERROR: Self = ErrorCode(-32002);
43
44 pub const CAPABILITY_NOT_SUPPORTED: Self = ErrorCode(-32003);
46
47 pub const RESOURCE_NOT_FOUND: Self = ErrorCode(-32004);
49
50 pub const RESOURCE_EXISTS: Self = ErrorCode(-32005);
52
53 pub const PERMISSION_DENIED: Self = ErrorCode(-32006);
55
56 pub const INVALID_STATE: Self = ErrorCode(-32007);
58
59 pub const CALLBACK_ERROR: Self = ErrorCode(-32008);
61
62 pub fn message(&self) -> &'static str {
64 match self.0 {
65 -32700 => "Parse error",
66 -32600 => "Invalid request",
67 -32601 => "Method not found",
68 -32602 => "Invalid params",
69 -32603 => "Internal error",
70 -32000 => "Server shutdown",
71 -32001 => "Transport error",
72 -32002 => "Timeout",
73 -32003 => "Capability not supported",
74 -32004 => "Resource not found",
75 -32005 => "Resource already exists",
76 -32006 => "Permission denied",
77 -32007 => "Invalid state",
78 -32008 => "Callback error",
79 _ => "Unknown error",
80 }
81 }
82
83 pub fn is_standard(&self) -> bool {
85 (-32700..=-32603).contains(&self.0)
86 }
87
88 pub fn is_custom(&self) -> bool {
90 (-32099..=-32000).contains(&self.0)
91 }
92}
93
94impl std::fmt::Display for ErrorCode {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(f, "{}", self.0)
97 }
98}
99
100impl From<i64> for ErrorCode {
101 fn from(code: i64) -> Self {
102 ErrorCode(code)
103 }
104}
105
106impl From<ErrorCode> for i64 {
107 fn from(code: ErrorCode) -> Self {
108 code.0
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn test_standard_error_codes() {
118 assert_eq!(ErrorCode::PARSE_ERROR.0, -32700);
119 assert_eq!(ErrorCode::INVALID_REQUEST.0, -32600);
120 assert_eq!(ErrorCode::METHOD_NOT_FOUND.0, -32601);
121 assert_eq!(ErrorCode::INVALID_PARAMS.0, -32602);
122 assert_eq!(ErrorCode::INTERNAL_ERROR.0, -32603);
123 }
124
125 #[test]
126 fn test_custom_error_codes() {
127 assert_eq!(ErrorCode::SERVER_SHUTDOWN.0, -32000);
128 assert_eq!(ErrorCode::TRANSPORT_ERROR.0, -32001);
129 assert_eq!(ErrorCode::TIMEOUT_ERROR.0, -32002);
130 }
131
132 #[test]
133 fn test_error_messages() {
134 assert_eq!(ErrorCode::PARSE_ERROR.message(), "Parse error");
135 assert_eq!(ErrorCode::METHOD_NOT_FOUND.message(), "Method not found");
136 assert_eq!(ErrorCode::SERVER_SHUTDOWN.message(), "Server shutdown");
137 }
138
139 #[test]
140 fn test_is_standard() {
141 assert!(ErrorCode::PARSE_ERROR.is_standard());
142 assert!(ErrorCode::INTERNAL_ERROR.is_standard());
143 assert!(!ErrorCode::SERVER_SHUTDOWN.is_standard());
144 }
145
146 #[test]
147 fn test_is_custom() {
148 assert!(ErrorCode::SERVER_SHUTDOWN.is_custom());
149 assert!(!ErrorCode::PARSE_ERROR.is_custom());
150 }
151
152 #[test]
153 fn test_error_code_serde() {
154 let code = ErrorCode::INVALID_PARAMS;
155 let json = serde_json::to_string(&code).unwrap();
156 assert_eq!(json, "-32602");
157
158 let decoded: ErrorCode = serde_json::from_str(&json).unwrap();
159 assert_eq!(decoded, code);
160 }
161}