1use std::{error, fmt};
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::Value;
5
6#[derive(Copy, Clone, Debug, Eq, PartialEq)]
8pub enum ErrorCode {
9 ParseError,
12 InvalidRequest,
14 MethodNotFound,
16 InvalidParams,
18 InternalError,
20 ServerError(i64),
22}
23
24impl From<i64> for ErrorCode {
25 fn from(code: i64) -> Self {
26 match code {
27 -32700 => ErrorCode::ParseError,
28 -32600 => ErrorCode::InvalidRequest,
29 -32601 => ErrorCode::MethodNotFound,
30 -32602 => ErrorCode::InvalidParams,
31 -32603 => ErrorCode::InternalError,
32 code => ErrorCode::ServerError(code),
33 }
34 }
35}
36
37impl Serialize for ErrorCode {
38 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39 where
40 S: Serializer,
41 {
42 serializer.serialize_i64(self.code())
43 }
44}
45
46impl<'de> Deserialize<'de> for ErrorCode {
47 fn deserialize<D>(deserializer: D) -> Result<ErrorCode, D::Error>
48 where
49 D: Deserializer<'de>,
50 {
51 let code: i64 = Deserialize::deserialize(deserializer)?;
52 Ok(ErrorCode::from(code))
53 }
54}
55
56impl ErrorCode {
57 pub fn code(&self) -> i64 {
59 match self {
60 ErrorCode::ParseError => -32700,
61 ErrorCode::InvalidRequest => -32600,
62 ErrorCode::MethodNotFound => -32601,
63 ErrorCode::InvalidParams => -32602,
64 ErrorCode::InternalError => -32603,
65 ErrorCode::ServerError(code) => *code,
66 }
67 }
68
69 pub fn description(&self) -> String {
71 let desc = match self {
72 ErrorCode::ParseError => "Parse error",
73 ErrorCode::InvalidRequest => "Invalid request",
74 ErrorCode::MethodNotFound => "Method not found",
75 ErrorCode::InvalidParams => "Invalid params",
76 ErrorCode::InternalError => "Internal error",
77 ErrorCode::ServerError(_) => "Server error",
78 };
79 desc.to_string()
80 }
81}
82
83#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
85#[serde(deny_unknown_fields)]
86pub struct Error {
87 pub code: ErrorCode,
90 pub message: String,
93 #[serde(skip_serializing_if = "Option::is_none")]
97 pub data: Option<Value>,
98}
99
100impl fmt::Display for Error {
101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102 write!(f, "{}: {}", self.code.description(), self.message)
103 }
104}
105
106impl error::Error for Error {}
107
108impl Error {
109 pub fn new(code: ErrorCode) -> Self {
111 Error {
112 message: code.description(),
113 code,
114 data: None,
115 }
116 }
117
118 pub fn parse_error() -> Self {
120 Self::new(ErrorCode::ParseError)
121 }
122
123 pub fn invalid_request() -> Self {
125 Self::new(ErrorCode::InvalidRequest)
126 }
127
128 pub fn method_not_found() -> Self {
130 Self::new(ErrorCode::MethodNotFound)
131 }
132
133 pub fn invalid_params<M>(message: M) -> Self
135 where
136 M: fmt::Display,
137 {
138 Error {
139 code: ErrorCode::InvalidParams,
140 message: format!("Invalid parameters: {}", message),
141 data: None,
142 }
143 }
144
145 pub fn invalid_params_with_details<M, D>(message: M, details: D) -> Self
147 where
148 M: fmt::Display,
149 D: fmt::Display,
150 {
151 Error {
152 code: ErrorCode::InvalidParams,
153 message: format!("Invalid parameters: {}", message),
154 data: Some(Value::String(details.to_string())),
155 }
156 }
157
158 pub fn internal_error() -> Self {
160 Self::new(ErrorCode::InternalError)
161 }
162
163 pub fn invalid_version() -> Self {
165 Error {
166 code: ErrorCode::InvalidRequest,
167 message: "Unsupported JSON-RPC protocol version".to_owned(),
168 data: None,
169 }
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn error_serialization() {
179 assert_eq!(
180 serde_json::to_string(&Error::parse_error()).unwrap(),
181 r#"{"code":-32700,"message":"Parse error"}"#
182 );
183 assert_eq!(
184 serde_json::to_string(&Error::invalid_request()).unwrap(),
185 r#"{"code":-32600,"message":"Invalid request"}"#
186 );
187 assert_eq!(
188 serde_json::to_string(&Error::method_not_found()).unwrap(),
189 r#"{"code":-32601,"message":"Method not found"}"#
190 );
191 assert_eq!(
192 serde_json::to_string(&Error::invalid_params("unexpected params")).unwrap(),
193 r#"{"code":-32602,"message":"Invalid parameters: unexpected params"}"#
194 );
195 assert_eq!(
196 serde_json::to_string(&Error::invalid_params_with_details("unexpected params", "details")).unwrap(),
197 r#"{"code":-32602,"message":"Invalid parameters: unexpected params","data":"details"}"#
198 );
199 assert_eq!(
200 serde_json::to_string(&Error::internal_error()).unwrap(),
201 r#"{"code":-32603,"message":"Internal error"}"#
202 );
203 assert_eq!(
204 serde_json::to_string(&Error::invalid_version()).unwrap(),
205 r#"{"code":-32600,"message":"Unsupported JSON-RPC protocol version"}"#
206 );
207 }
208}