rpc_router/rpc_response/
rpc_error.rs

1use crate::Error;
2use serde::{Deserialize, Serialize};
3use serde_json::{Value, json};
4
5/// Represents the JSON-RPC 2.0 Error Object.
6/// <https://www.jsonrpc.org/specification#error_object>
7#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
8pub struct RpcError {
9	/// A Number that indicates the error type that occurred.
10	pub code: i64,
11
12	/// A String providing a short description of the error.
13	pub message: String,
14
15	/// A Primitive or Structured value that contains additional information about the error.
16	/// This may be omitted.
17	#[serde(skip_serializing_if = "Option::is_none")]
18	pub data: Option<Value>,
19}
20
21// region:    --- Predefined Errors
22// https://www.jsonrpc.org/specification#error_object
23impl RpcError {
24	pub const CODE_PARSE_ERROR: i64 = -32700;
25	pub const CODE_INVALID_REQUEST: i64 = -32600;
26	pub const CODE_METHOD_NOT_FOUND: i64 = -32601;
27	pub const CODE_INVALID_PARAMS: i64 = -32602;
28	pub const CODE_INTERNAL_ERROR: i64 = -32603;
29	// -32000 to -32099: Server error. Reserved for implementation-defined server-errors.
30
31	pub fn from_parse_error(data: Option<Value>) -> Self {
32		Self {
33			code: Self::CODE_PARSE_ERROR,
34			message: "Parse error".to_string(),
35			data,
36		}
37	}
38
39	pub fn from_invalid_request(data: Option<Value>) -> Self {
40		Self {
41			code: Self::CODE_INVALID_REQUEST,
42			message: "Invalid Request".to_string(),
43			data,
44		}
45	}
46
47	pub fn from_method_not_found(data: Option<Value>) -> Self {
48		Self {
49			code: Self::CODE_METHOD_NOT_FOUND,
50			message: "Method not found".to_string(),
51			data,
52		}
53	}
54
55	pub fn from_invalid_params(data: Option<Value>) -> Self {
56		Self {
57			code: Self::CODE_INVALID_PARAMS,
58			message: "Invalid params".to_string(),
59			data,
60		}
61	}
62
63	pub fn from_internal_error(data: Option<Value>) -> Self {
64		Self {
65			code: Self::CODE_INTERNAL_ERROR,
66			message: "Internal error".to_string(),
67			data,
68		}
69	}
70
71	/// Helper to create an RpcError with optional data representing the original error string.
72	fn new(code: i64, message: impl Into<String>, error: Option<&dyn std::error::Error>) -> Self {
73		let data = error.map(|e| json!(e.to_string()));
74		Self {
75			code,
76			message: message.into(),
77			data,
78		}
79	}
80}
81// endregion: --- Predefined Errors
82
83// region:    --- From RouterError
84
85impl From<&Error> for RpcError {
86	/// Converts a router `Error` into a JSON-RPC `RpcError`.
87	fn from(err: &Error) -> Self {
88		match err {
89			Error::ParamsParsing(p) => Self::new(Self::CODE_INVALID_PARAMS, "Invalid params", Some(p)),
90			Error::ParamsMissingButRequested => Self::new(Self::CODE_INVALID_PARAMS, "Invalid params", Some(err)),
91			Error::MethodUnknown => Self::new(Self::CODE_METHOD_NOT_FOUND, "Method not found", Some(err)),
92			Error::FromResources(fr_err) => Self::new(Self::CODE_INTERNAL_ERROR, "Internal error", Some(fr_err)),
93			Error::HandlerResultSerialize(s_err) => Self::new(Self::CODE_INTERNAL_ERROR, "Internal error", Some(s_err)),
94			// NOTE: For HandlerError, we use a generic Internal Error.
95			//       A future enhancement could involve a trait on the error
96			//       wrapped by HandlerError to provide specific RpcError details.
97			Error::Handler(h_err) => Self::new(Self::CODE_INTERNAL_ERROR, "Internal error", Some(h_err)),
98		}
99	}
100}
101
102// endregion: --- From RouterError
103
104// region:    --- From CallError
105
106// We also implement From<CallError> for RpcError for convenience, although
107// the direct conversion from CallError to RpcResponse is often more useful.
108impl From<crate::CallError> for RpcError {
109	fn from(call_error: crate::CallError) -> Self {
110		// Reuse the logic from From<&RouterError>
111		RpcError::from(&call_error.error)
112	}
113}
114
115impl From<&crate::CallError> for RpcError {
116	fn from(call_error: &crate::CallError) -> Self {
117		// Reuse the logic from From<&RouterError>
118		RpcError::from(&call_error.error)
119	}
120}
121
122// endregion: --- From CallError