jsonrpc_types/
error.rs

1use std::{error, fmt};
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::Value;
5
6/// JSON-RPC Error Code.
7#[derive(Copy, Clone, Debug, Eq, PartialEq)]
8pub enum ErrorCode {
9    /// Invalid JSON was received by the server.
10    /// An error occurred on the server while parsing the JSON text.
11    ParseError,
12    /// The JSON sent is not a valid Request object.
13    InvalidRequest,
14    /// The method does not exist / is not available.
15    MethodNotFound,
16    /// Invalid method parameter(s).
17    InvalidParams,
18    /// Internal JSON-RPC error.
19    InternalError,
20    /// Reserved for implementation-defined server-errors.
21    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    /// Returns integer code value.
58    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    /// Returns human-readable description.
70    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/// JSON-RPC Error Object.
84#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
85#[serde(deny_unknown_fields)]
86pub struct Error {
87    /// A Number that indicates the error type that occurred.
88    /// This MUST be an integer.
89    pub code: ErrorCode,
90    /// A String providing a short description of the error.
91    /// The message SHOULD be limited to a concise single sentence.
92    pub message: String,
93    /// A Primitive or Structured value that contains additional information about the error.
94    /// This may be omitted.
95    /// The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
96    #[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    /// Wraps given `ErrorCode`.
110    pub fn new(code: ErrorCode) -> Self {
111        Error {
112            message: code.description(),
113            code,
114            data: None,
115        }
116    }
117
118    /// Creates a new `ParseError` error.
119    pub fn parse_error() -> Self {
120        Self::new(ErrorCode::ParseError)
121    }
122
123    /// Creates a new `InvalidRequest` error.
124    pub fn invalid_request() -> Self {
125        Self::new(ErrorCode::InvalidRequest)
126    }
127
128    /// Creates a new `MethodNotFound` error.
129    pub fn method_not_found() -> Self {
130        Self::new(ErrorCode::MethodNotFound)
131    }
132
133    /// Creates a new `InvalidParams` error with given message.
134    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    /// Creates a new `InvalidParams` error with given message and details.
146    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    /// Creates a new `InternalError` error.
159    pub fn internal_error() -> Self {
160        Self::new(ErrorCode::InternalError)
161    }
162
163    /// Creates a new `InvalidRequest` error with invalid version description.
164    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}