jsonrpc_core/types/
error.rs

1//! jsonrpc errors
2use super::Value;
3use serde::de::{Deserialize, Deserializer};
4use serde::ser::{Serialize, Serializer};
5use std::fmt;
6
7/// JSONRPC error code
8#[derive(Debug, PartialEq, Clone)]
9pub enum ErrorCode {
10	/// Invalid JSON was received by the server.
11	/// An error occurred on the server while parsing the JSON text.
12	ParseError,
13	/// The JSON sent is not a valid Request object.
14	InvalidRequest,
15	/// The method does not exist / is not available.
16	MethodNotFound,
17	/// Invalid method parameter(s).
18	InvalidParams,
19	/// Internal JSON-RPC error.
20	InternalError,
21	/// Reserved for implementation-defined server-errors.
22	ServerError(i64),
23}
24
25impl ErrorCode {
26	/// Returns integer code value
27	pub fn code(&self) -> i64 {
28		match *self {
29			ErrorCode::ParseError => -32700,
30			ErrorCode::InvalidRequest => -32600,
31			ErrorCode::MethodNotFound => -32601,
32			ErrorCode::InvalidParams => -32602,
33			ErrorCode::InternalError => -32603,
34			ErrorCode::ServerError(code) => code,
35		}
36	}
37
38	/// Returns human-readable description
39	pub fn description(&self) -> String {
40		let desc = match *self {
41			ErrorCode::ParseError => "Parse error",
42			ErrorCode::InvalidRequest => "Invalid request",
43			ErrorCode::MethodNotFound => "Method not found",
44			ErrorCode::InvalidParams => "Invalid params",
45			ErrorCode::InternalError => "Internal error",
46			ErrorCode::ServerError(_) => "Server error",
47		};
48		desc.to_string()
49	}
50}
51
52impl From<i64> for ErrorCode {
53	fn from(code: i64) -> Self {
54		match code {
55			-32700 => ErrorCode::ParseError,
56			-32600 => ErrorCode::InvalidRequest,
57			-32601 => ErrorCode::MethodNotFound,
58			-32602 => ErrorCode::InvalidParams,
59			-32603 => ErrorCode::InternalError,
60			code => ErrorCode::ServerError(code),
61		}
62	}
63}
64
65impl<'a> Deserialize<'a> for ErrorCode {
66	fn deserialize<D>(deserializer: D) -> Result<ErrorCode, D::Error>
67	where
68		D: Deserializer<'a>,
69	{
70		let code: i64 = Deserialize::deserialize(deserializer)?;
71		Ok(ErrorCode::from(code))
72	}
73}
74
75impl Serialize for ErrorCode {
76	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
77	where
78		S: Serializer,
79	{
80		serializer.serialize_i64(self.code())
81	}
82}
83
84/// Error object as defined in Spec
85#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
86#[serde(deny_unknown_fields)]
87pub struct Error {
88	/// Code
89	pub code: ErrorCode,
90	/// Message
91	pub message: String,
92	/// Optional data
93	#[serde(skip_serializing_if = "Option::is_none")]
94	pub data: Option<Value>,
95}
96
97impl Error {
98	/// Wraps given `ErrorCode`
99	pub fn new(code: ErrorCode) -> Self {
100		Error {
101			message: code.description(),
102			code,
103			data: None,
104		}
105	}
106
107	/// Creates new `ParseError`
108	pub fn parse_error() -> Self {
109		Self::new(ErrorCode::ParseError)
110	}
111
112	/// Creates new `InvalidRequest`
113	pub fn invalid_request() -> Self {
114		Self::new(ErrorCode::InvalidRequest)
115	}
116
117	/// Creates new `MethodNotFound`
118	pub fn method_not_found() -> Self {
119		Self::new(ErrorCode::MethodNotFound)
120	}
121
122	/// Creates new `InvalidParams`
123	pub fn invalid_params<M>(message: M) -> Self
124	where
125		M: Into<String>,
126	{
127		Error {
128			code: ErrorCode::InvalidParams,
129			message: message.into(),
130			data: None,
131		}
132	}
133
134	/// Creates `InvalidParams` for given parameter, with details.
135	pub fn invalid_params_with_details<M, T>(message: M, details: T) -> Error
136	where
137		M: Into<String>,
138		T: fmt::Debug,
139	{
140		Error {
141			code: ErrorCode::InvalidParams,
142			message: format!("Invalid parameters: {}", message.into()),
143			data: Some(Value::String(format!("{:?}", details))),
144		}
145	}
146
147	/// Creates new `InternalError`
148	pub fn internal_error() -> Self {
149		Self::new(ErrorCode::InternalError)
150	}
151
152	/// Creates new `InvalidRequest` with invalid version description
153	pub fn invalid_version() -> Self {
154		Error {
155			code: ErrorCode::InvalidRequest,
156			message: "Unsupported JSON-RPC protocol version".to_owned(),
157			data: None,
158		}
159	}
160}
161
162impl std::fmt::Display for Error {
163	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
164		write!(f, "{}: {}", self.code.description(), self.message)
165	}
166}
167
168impl std::error::Error for Error {}