1use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use serde_json::Value;
8use std::fmt;
9
10use crate::types::RequestId;
11
12pub const JSONRPC_VERSION: &str = "2.0";
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct JsonRpcVersion;
18
19impl Serialize for JsonRpcVersion {
20 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21 where
22 S: Serializer,
23 {
24 serializer.serialize_str(JSONRPC_VERSION)
25 }
26}
27
28impl<'de> Deserialize<'de> for JsonRpcVersion {
29 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30 where
31 D: Deserializer<'de>,
32 {
33 let version = String::deserialize(deserializer)?;
34 if version == JSONRPC_VERSION {
35 Ok(JsonRpcVersion)
36 } else {
37 Err(serde::de::Error::custom(format!(
38 "Invalid JSON-RPC version: expected '{JSONRPC_VERSION}', got '{version}'"
39 )))
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct JsonRpcRequest {
47 pub jsonrpc: JsonRpcVersion,
49 pub method: String,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub params: Option<Value>,
54 pub id: RequestId,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct JsonRpcResponse {
61 pub jsonrpc: JsonRpcVersion,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub result: Option<Value>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub error: Option<JsonRpcError>,
69 pub id: Option<RequestId>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct JsonRpcNotification {
76 pub jsonrpc: JsonRpcVersion,
78 pub method: String,
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub params: Option<Value>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct JsonRpcError {
88 pub code: i32,
90 pub message: String,
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub data: Option<Value>,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
99#[serde(transparent)]
100pub struct JsonRpcBatch<T> {
101 pub items: Vec<T>,
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum JsonRpcErrorCode {
108 ParseError,
110 InvalidRequest,
112 MethodNotFound,
114 InvalidParams,
116 InternalError,
118 ApplicationError(i32),
120}
121
122impl JsonRpcErrorCode {
123 pub fn code(&self) -> i32 {
125 match self {
126 Self::ParseError => -32700,
127 Self::InvalidRequest => -32600,
128 Self::MethodNotFound => -32601,
129 Self::InvalidParams => -32602,
130 Self::InternalError => -32603,
131 Self::ApplicationError(code) => *code,
132 }
133 }
134
135 pub fn message(&self) -> &'static str {
137 match self {
138 Self::ParseError => "Parse error",
139 Self::InvalidRequest => "Invalid Request",
140 Self::MethodNotFound => "Method not found",
141 Self::InvalidParams => "Invalid params",
142 Self::InternalError => "Internal error",
143 Self::ApplicationError(_) => "Application error",
144 }
145 }
146}
147
148impl fmt::Display for JsonRpcErrorCode {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 write!(f, "{} ({})", self.message(), self.code())
151 }
152}
153
154impl From<JsonRpcErrorCode> for JsonRpcError {
155 fn from(code: JsonRpcErrorCode) -> Self {
156 Self {
157 code: code.code(),
158 message: code.message().to_string(),
159 data: None,
160 }
161 }
162}
163
164impl From<i32> for JsonRpcErrorCode {
165 fn from(code: i32) -> Self {
166 match code {
167 -32700 => Self::ParseError,
168 -32600 => Self::InvalidRequest,
169 -32601 => Self::MethodNotFound,
170 -32602 => Self::InvalidParams,
171 -32603 => Self::InternalError,
172 other => Self::ApplicationError(other),
173 }
174 }
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179#[serde(untagged)]
180pub enum JsonRpcMessage {
181 Request(JsonRpcRequest),
183 Response(JsonRpcResponse),
185 Notification(JsonRpcNotification),
187 RequestBatch(JsonRpcBatch<JsonRpcRequest>),
189 ResponseBatch(JsonRpcBatch<JsonRpcResponse>),
191 MessageBatch(JsonRpcBatch<JsonRpcMessage>),
193}
194
195impl JsonRpcRequest {
196 pub fn new(method: String, params: Option<Value>, id: RequestId) -> Self {
198 Self {
199 jsonrpc: JsonRpcVersion,
200 method,
201 params,
202 id,
203 }
204 }
205
206 pub fn without_params(method: String, id: RequestId) -> Self {
208 Self::new(method, None, id)
209 }
210
211 pub fn with_params<P: Serialize>(
213 method: String,
214 params: P,
215 id: RequestId,
216 ) -> Result<Self, serde_json::Error> {
217 let params_value = serde_json::to_value(params)?;
218 Ok(Self::new(method, Some(params_value), id))
219 }
220}
221
222impl JsonRpcResponse {
223 pub fn success(result: Value, id: RequestId) -> Self {
225 Self {
226 jsonrpc: JsonRpcVersion,
227 result: Some(result),
228 error: None,
229 id: Some(id),
230 }
231 }
232
233 pub fn error(error: JsonRpcError, id: Option<RequestId>) -> Self {
235 Self {
236 jsonrpc: JsonRpcVersion,
237 result: None,
238 error: Some(error),
239 id,
240 }
241 }
242
243 pub fn parse_error(message: Option<String>) -> Self {
245 let error = JsonRpcError {
246 code: JsonRpcErrorCode::ParseError.code(),
247 message: message.unwrap_or_else(|| JsonRpcErrorCode::ParseError.message().to_string()),
248 data: None,
249 };
250 Self::error(error, None)
251 }
252
253 pub fn is_success(&self) -> bool {
255 self.error.is_none()
256 }
257
258 pub fn is_error(&self) -> bool {
260 self.error.is_some()
261 }
262}
263
264impl JsonRpcNotification {
265 pub fn new(method: String, params: Option<Value>) -> Self {
267 Self {
268 jsonrpc: JsonRpcVersion,
269 method,
270 params,
271 }
272 }
273
274 pub fn without_params(method: String) -> Self {
276 Self::new(method, None)
277 }
278
279 pub fn with_params<P: Serialize>(method: String, params: P) -> Result<Self, serde_json::Error> {
281 let params_value = serde_json::to_value(params)?;
282 Ok(Self::new(method, Some(params_value)))
283 }
284}
285
286impl<T> JsonRpcBatch<T> {
287 pub fn new(items: Vec<T>) -> Self {
289 Self { items }
290 }
291
292 pub fn empty() -> Self {
294 Self::new(Vec::new())
295 }
296
297 pub fn push(&mut self, item: T) {
299 self.items.push(item);
300 }
301
302 pub fn len(&self) -> usize {
304 self.items.len()
305 }
306
307 pub fn is_empty(&self) -> bool {
309 self.items.is_empty()
310 }
311
312 pub fn iter(&self) -> impl Iterator<Item = &T> {
314 self.items.iter()
315 }
316}
317
318impl<T> IntoIterator for JsonRpcBatch<T> {
319 type Item = T;
320 type IntoIter = std::vec::IntoIter<T>;
321
322 fn into_iter(self) -> Self::IntoIter {
323 self.items.into_iter()
324 }
325}
326
327impl<T> From<Vec<T>> for JsonRpcBatch<T> {
328 fn from(items: Vec<T>) -> Self {
329 Self::new(items)
330 }
331}
332
333pub mod utils {
335 use super::*;
336
337 pub fn parse_message(json: &str) -> Result<JsonRpcMessage, serde_json::Error> {
339 serde_json::from_str(json)
340 }
341
342 pub fn serialize_message(message: &JsonRpcMessage) -> Result<String, serde_json::Error> {
344 serde_json::to_string(message)
345 }
346
347 pub fn is_batch(json: &str) -> bool {
349 json.trim_start().starts_with('[')
350 }
351
352 pub fn extract_method(json: &str) -> Option<String> {
354 if let Ok(value) = serde_json::from_str::<serde_json::Value>(json)
356 && let Some(method) = value.get("method")
357 {
358 return method.as_str().map(String::from);
359 }
360 None
361 }
362}
363
364#[cfg(test)]
365mod tests {
366 use super::*;
367 use serde_json::json;
368
369 #[test]
370 fn test_jsonrpc_version() {
371 let version = JsonRpcVersion;
372 let json = serde_json::to_string(&version).unwrap();
373 assert_eq!(json, "\"2.0\"");
374
375 let parsed: JsonRpcVersion = serde_json::from_str(&json).unwrap();
376 assert_eq!(parsed, version);
377 }
378
379 #[test]
380 fn test_request_creation() {
381 let request = JsonRpcRequest::new(
382 "test_method".to_string(),
383 Some(json!({"key": "value"})),
384 RequestId::String("test-id".to_string()),
385 );
386
387 assert_eq!(request.method, "test_method");
388 assert!(request.params.is_some());
389 }
390
391 #[test]
392 fn test_response_creation() {
393 let response = JsonRpcResponse::success(
394 json!({"result": "success"}),
395 RequestId::String("test-id".to_string()),
396 );
397
398 assert!(response.is_success());
399 assert!(!response.is_error());
400 assert!(response.result.is_some());
401 assert!(response.error.is_none());
402 }
403
404 #[test]
405 fn test_error_response() {
406 let error = JsonRpcError::from(JsonRpcErrorCode::MethodNotFound);
407 let response =
408 JsonRpcResponse::error(error, Some(RequestId::String("test-id".to_string())));
409
410 assert!(!response.is_success());
411 assert!(response.is_error());
412 assert!(response.result.is_none());
413 assert!(response.error.is_some());
414 }
415
416 #[test]
417 fn test_notification() {
418 let notification = JsonRpcNotification::without_params("test_notification".to_string());
419 assert_eq!(notification.method, "test_notification");
420 assert!(notification.params.is_none());
421 }
422
423 #[test]
424 fn test_batch() {
425 let mut batch = JsonRpcBatch::<JsonRpcRequest>::empty();
426 assert!(batch.is_empty());
427
428 batch.push(JsonRpcRequest::without_params(
429 "method1".to_string(),
430 RequestId::String("1".to_string()),
431 ));
432 batch.push(JsonRpcRequest::without_params(
433 "method2".to_string(),
434 RequestId::String("2".to_string()),
435 ));
436
437 assert_eq!(batch.len(), 2);
438 assert!(!batch.is_empty());
439 }
440
441 #[test]
442 fn test_serialization() {
443 let request = JsonRpcRequest::new(
444 "test_method".to_string(),
445 Some(json!({"param": "value"})),
446 RequestId::String("123".to_string()),
447 );
448
449 let json = serde_json::to_string(&request).unwrap();
450 let parsed: JsonRpcRequest = serde_json::from_str(&json).unwrap();
451
452 assert_eq!(parsed.method, request.method);
453 assert_eq!(parsed.params, request.params);
454 }
455
456 #[test]
457 fn test_utils() {
458 let json = r#"{"jsonrpc":"2.0","method":"test","id":"123"}"#;
459
460 assert!(!utils::is_batch(json));
461 assert_eq!(utils::extract_method(json), Some("test".to_string()));
462
463 let batch_json = r#"[{"jsonrpc":"2.0","method":"test","id":"123"}]"#;
464 assert!(utils::is_batch(batch_json));
465 }
466
467 #[test]
468 fn test_error_codes() {
469 let parse_error = JsonRpcErrorCode::ParseError;
470 assert_eq!(parse_error.code(), -32700);
471 assert_eq!(parse_error.message(), "Parse error");
472
473 let app_error = JsonRpcErrorCode::ApplicationError(-32001);
474 assert_eq!(app_error.code(), -32001);
475 }
476}