1use serde::{Deserialize, Serialize};
6use serde_json::value::RawValue;
7use serde_json::Value;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[serde(untagged)]
15pub enum RpcId {
16 Number(i64),
17 String(String),
18 Null,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct RpcRequest {
35 pub jsonrpc: String,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub id: Option<RpcId>,
38 pub method: String,
39 pub params: Value,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct RpcResponse {
70 pub jsonrpc: String,
71 pub id: Option<RpcId>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub result: Option<Box<RawValue>>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub error: Option<RpcError>,
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub partial: Option<bool>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct RpcError {
83 pub code: i32,
84 pub message: String,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub data: Option<Value>,
87}
88
89pub const PARSE_ERROR: i32 = -32700;
91pub const INVALID_REQUEST: i32 = -32600;
92pub const METHOD_NOT_FOUND: i32 = -32601;
93pub const INVALID_PARAMS: i32 = -32602;
94pub const INTERNAL_ERROR: i32 = -32603;
95
96pub fn ok(id: Option<RpcId>, result: Box<RawValue>) -> RpcResponse {
98 RpcResponse {
99 jsonrpc: "2.0".to_string(),
100 id,
101 result: Some(result),
102 error: None,
103 partial: None,
104 }
105}
106
107pub fn err(id: Option<RpcId>, code: i32, message: String, data: Option<Value>) -> RpcResponse {
109 RpcResponse {
110 jsonrpc: "2.0".to_string(),
111 id,
112 result: None,
113 error: Some(RpcError {
114 code,
115 message,
116 data,
117 }),
118 partial: None,
119 }
120}
121
122pub fn ok_partial(id: Option<RpcId>, result: Box<RawValue>) -> RpcResponse {
124 RpcResponse {
125 jsonrpc: "2.0".to_string(),
126 id,
127 result: Some(result),
128 error: None,
129 partial: Some(true),
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use serde_json::json;
137
138 #[test]
139 fn test_rpc_id_serialization() {
140 let id = RpcId::Number(42);
142 let json = serde_json::to_string(&id).unwrap();
143 assert_eq!(json, "42");
144 let parsed: RpcId = serde_json::from_str(&json).unwrap();
145 assert_eq!(parsed, id);
146
147 let id = RpcId::String("abc-123".to_string());
149 let json = serde_json::to_string(&id).unwrap();
150 assert_eq!(json, r#""abc-123""#);
151 let parsed: RpcId = serde_json::from_str(&json).unwrap();
152 assert_eq!(parsed, id);
153
154 let id = RpcId::Null;
156 let json = serde_json::to_string(&id).unwrap();
157 assert_eq!(json, "null");
158 let parsed: RpcId = serde_json::from_str(&json).unwrap();
159 assert_eq!(parsed, id);
160 }
161
162 #[test]
163 fn test_request_serialization() {
164 let request = RpcRequest {
165 jsonrpc: "2.0".to_string(),
166 id: Some(RpcId::Number(1)),
167 method: "test.method".to_string(),
168 params: json!({"key": "value"}),
169 };
170
171 let json = serde_json::to_value(&request).unwrap();
172 assert_eq!(json["jsonrpc"], "2.0");
173 assert_eq!(json["id"], 1);
174 assert_eq!(json["method"], "test.method");
175 assert_eq!(json["params"]["key"], "value");
176
177 let parsed: RpcRequest = serde_json::from_value(json).unwrap();
179 assert_eq!(parsed.jsonrpc, "2.0");
180 assert_eq!(parsed.id, Some(RpcId::Number(1)));
181 assert_eq!(parsed.method, "test.method");
182 }
183
184 #[test]
185 fn test_response_ok() {
186 let raw = serde_json::value::to_raw_value(&json!({"status": "ok"})).unwrap();
187 let response = ok(Some(RpcId::Number(1)), raw);
188
189 assert_eq!(response.jsonrpc, "2.0");
190 assert_eq!(response.id, Some(RpcId::Number(1)));
191 assert!(response.result.is_some());
192 assert!(response.error.is_none());
193
194 let serialized = serde_json::to_string(&response).unwrap();
195 let json: serde_json::Value = serde_json::from_str(&serialized).unwrap();
196 assert_eq!(json["result"]["status"], "ok");
197 assert!(json.get("error").is_none());
198 }
199
200 #[test]
201 fn test_response_error() {
202 let response = err(
203 Some(RpcId::Number(2)),
204 METHOD_NOT_FOUND,
205 "Method not found".to_string(),
206 Some(json!({"method": "unknown.method"})),
207 );
208
209 assert_eq!(response.jsonrpc, "2.0");
210 assert_eq!(response.id, Some(RpcId::Number(2)));
211 assert!(response.result.is_none());
212 assert!(response.error.is_some());
213
214 let error = response.error.unwrap();
215 assert_eq!(error.code, METHOD_NOT_FOUND);
216 assert_eq!(error.message, "Method not found");
217 assert_eq!(error.data.unwrap()["method"], "unknown.method");
218 }
219
220 #[test]
221 fn test_notification_no_id() {
222 let request = RpcRequest {
223 jsonrpc: "2.0".to_string(),
224 id: None,
225 method: "notification".to_string(),
226 params: json!(null),
227 };
228
229 let json = serde_json::to_value(&request).unwrap();
230 assert!(json["id"].is_null() || !json.as_object().unwrap().contains_key("id"));
231 }
232}