1use serde::{Deserialize, Serialize};
38use serde_json::Value;
39use uuid::Uuid;
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
46pub struct JsonRpcRequest {
47 pub jsonrpc: String,
49
50 pub id: RequestId,
52
53 pub method: String,
55
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub params: Option<Value>,
59}
60
61impl JsonRpcRequest {
62 pub fn new(id: impl Into<RequestId>, method: impl Into<String>, params: Value) -> Self {
77 Self {
78 jsonrpc: "2.0".to_string(),
79 id: id.into(),
80 method: method.into(),
81 params: Some(params),
82 }
83 }
84
85 pub fn without_params(id: impl Into<RequestId>, method: impl Into<String>) -> Self {
95 Self {
96 jsonrpc: "2.0".to_string(),
97 id: id.into(),
98 method: method.into(),
99 params: None,
100 }
101 }
102
103 pub fn with_random_id(method: impl Into<String>, params: Value) -> Self {
107 Self::new(Uuid::new_v4().to_string(), method, params)
108 }
109
110 pub fn has_params(&self) -> bool {
112 self.params.is_some()
113 }
114
115 pub fn params_as<T>(&self) -> Result<T, serde_json::Error>
140 where
141 T: for<'de> Deserialize<'de>,
142 {
143 match &self.params {
144 Some(params) => serde_json::from_value(params.clone()),
145 None => serde_json::from_value(Value::Null),
146 }
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
155pub struct JsonRpcResponse {
156 pub jsonrpc: String,
158
159 pub id: RequestId,
161
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub result: Option<Value>,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub error: Option<JsonRpcError>,
169}
170
171impl JsonRpcResponse {
172 pub fn success(id: impl Into<RequestId>, result: Value) -> Self {
183 Self {
184 jsonrpc: "2.0".to_string(),
185 id: id.into(),
186 result: Some(result),
187 error: None,
188 }
189 }
190
191 pub fn error(id: impl Into<RequestId>, error: JsonRpcError) -> Self {
204 Self {
205 jsonrpc: "2.0".to_string(),
206 id: id.into(),
207 result: None,
208 error: Some(error),
209 }
210 }
211
212 pub fn is_success(&self) -> bool {
214 self.result.is_some() && self.error.is_none()
215 }
216
217 pub fn is_error(&self) -> bool {
219 self.error.is_some()
220 }
221
222 pub fn result_as<T>(&self) -> Result<T, Box<dyn std::error::Error + Send + Sync>>
227 where
228 T: for<'de> Deserialize<'de>,
229 {
230 match (&self.result, &self.error) {
231 (Some(result), None) => Ok(serde_json::from_value(result.clone())?),
232 (None, Some(error)) => Err(format!("JSON-RPC error: {}", error).into()),
233 _ => Err("Invalid response: both result and error are present or missing".into()),
234 }
235 }
236}
237
238#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
243pub struct JsonRpcNotification {
244 pub jsonrpc: String,
246
247 pub method: String,
249
250 #[serde(skip_serializing_if = "Option::is_none")]
252 pub params: Option<Value>,
253}
254
255impl JsonRpcNotification {
256 pub fn new(method: impl Into<String>, params: Value) -> Self {
270 Self {
271 jsonrpc: "2.0".to_string(),
272 method: method.into(),
273 params: Some(params),
274 }
275 }
276
277 pub fn without_params(method: impl Into<String>) -> Self {
287 Self {
288 jsonrpc: "2.0".to_string(),
289 method: method.into(),
290 params: None,
291 }
292 }
293
294 pub fn has_params(&self) -> bool {
296 self.params.is_some()
297 }
298
299 pub fn params_as<T>(&self) -> Result<T, serde_json::Error>
301 where
302 T: for<'de> Deserialize<'de>,
303 {
304 match &self.params {
305 Some(params) => serde_json::from_value(params.clone()),
306 None => serde_json::from_value(Value::Null),
307 }
308 }
309}
310
311#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
316pub struct JsonRpcError {
317 pub code: i32,
319
320 pub message: String,
322
323 #[serde(skip_serializing_if = "Option::is_none")]
325 pub data: Option<Value>,
326}
327
328impl JsonRpcError {
329 pub fn new(code: i32, message: impl Into<String>, data: Option<Value>) -> Self {
340 Self {
341 code,
342 message: message.into(),
343 data,
344 }
345 }
346
347 pub fn parse_error() -> Self {
351 Self::new(-32700, "Parse error", None)
352 }
353
354 pub fn invalid_request(details: impl Into<String>) -> Self {
358 Self::new(
359 -32600,
360 "Invalid Request",
361 Some(Value::String(details.into())),
362 )
363 }
364
365 pub fn method_not_found(method: impl Into<String>) -> Self {
369 Self::new(
370 -32601,
371 "Method not found",
372 Some(Value::String(format!(
373 "Method '{}' not found",
374 method.into()
375 ))),
376 )
377 }
378
379 pub fn invalid_params(details: impl Into<String>) -> Self {
383 Self::new(
384 -32602,
385 "Invalid params",
386 Some(Value::String(details.into())),
387 )
388 }
389
390 pub fn internal_error(details: impl Into<String>) -> Self {
394 Self::new(
395 -32603,
396 "Internal error",
397 Some(Value::String(details.into())),
398 )
399 }
400
401 pub fn application_error(
417 code: i32,
418 message: impl Into<String>,
419 details: impl Into<String>,
420 ) -> Self {
421 Self::new(code, message, Some(Value::String(details.into())))
422 }
423
424 pub fn is_standard_error(&self) -> bool {
426 matches!(self.code, -32700..=-32600)
427 }
428
429 pub fn is_application_error(&self) -> bool {
431 matches!(self.code, -32099..=-32000)
432 }
433}
434
435impl std::fmt::Display for JsonRpcError {
436 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437 write!(f, "JSON-RPC Error {}: {}", self.code, self.message)?;
438 if let Some(data) = &self.data {
439 write!(f, " ({})", data)?;
440 }
441 Ok(())
442 }
443}
444
445impl std::error::Error for JsonRpcError {}
446
447#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
452#[serde(untagged)]
453pub enum RequestId {
454 String(String),
456 Number(i64),
458 Null,
460}
461
462impl From<String> for RequestId {
463 fn from(s: String) -> Self {
464 Self::String(s)
465 }
466}
467
468impl From<&str> for RequestId {
469 fn from(s: &str) -> Self {
470 Self::String(s.to_string())
471 }
472}
473
474impl From<i64> for RequestId {
475 fn from(n: i64) -> Self {
476 Self::Number(n)
477 }
478}
479
480impl From<i32> for RequestId {
481 fn from(n: i32) -> Self {
482 Self::Number(n as i64)
483 }
484}
485
486impl std::fmt::Display for RequestId {
487 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
488 match self {
489 Self::String(s) => write!(f, "{}", s),
490 Self::Number(n) => write!(f, "{}", n),
491 Self::Null => write!(f, "null"),
492 }
493 }
494}
495
496#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
501#[serde(untagged)]
502pub enum JsonRpcMessage {
503 Request(JsonRpcRequest),
505 Response(JsonRpcResponse),
507 Notification(JsonRpcNotification),
509}
510
511impl JsonRpcMessage {
512 pub fn method(&self) -> Option<&str> {
514 match self {
515 Self::Request(req) => Some(&req.method),
516 Self::Notification(notif) => Some(¬if.method),
517 Self::Response(_) => None,
518 }
519 }
520
521 pub fn id(&self) -> Option<&RequestId> {
523 match self {
524 Self::Request(req) => Some(&req.id),
525 Self::Response(resp) => Some(&resp.id),
526 Self::Notification(_) => None,
527 }
528 }
529
530 pub fn expects_response(&self) -> bool {
532 matches!(self, Self::Request(_))
533 }
534}
535
536impl From<JsonRpcRequest> for JsonRpcMessage {
537 fn from(req: JsonRpcRequest) -> Self {
538 Self::Request(req)
539 }
540}
541
542impl From<JsonRpcResponse> for JsonRpcMessage {
543 fn from(resp: JsonRpcResponse) -> Self {
544 Self::Response(resp)
545 }
546}
547
548impl From<JsonRpcNotification> for JsonRpcMessage {
549 fn from(notif: JsonRpcNotification) -> Self {
550 Self::Notification(notif)
551 }
552}
553
554pub type JsonRpcId = RequestId;
556
557#[cfg(test)]
558mod tests {
559 use super::*;
560 use serde_json::json;
561
562 #[test]
563 fn test_request_creation() {
564 let request = JsonRpcRequest::new("1", "test_method", json!({"param": "value"}));
565
566 assert_eq!(request.jsonrpc, "2.0");
567 assert_eq!(request.id, RequestId::String("1".to_string()));
568 assert_eq!(request.method, "test_method");
569 assert!(request.has_params());
570 }
571
572 #[test]
573 fn test_request_without_params() {
574 let request = JsonRpcRequest::without_params("1", "test_method");
575
576 assert!(!request.has_params());
577 assert_eq!(request.params, None);
578 }
579
580 #[test]
581 fn test_success_response() {
582 let response = JsonRpcResponse::success("1", json!({"result": "ok"}));
583
584 assert!(response.is_success());
585 assert!(!response.is_error());
586 assert_eq!(response.id, RequestId::String("1".to_string()));
587 }
588
589 #[test]
590 fn test_error_response() {
591 let error = JsonRpcError::method_not_found("unknown");
592 let response = JsonRpcResponse::error("1", error);
593
594 assert!(!response.is_success());
595 assert!(response.is_error());
596 assert_eq!(response.error.as_ref().unwrap().code, -32601);
597 }
598
599 #[test]
600 fn test_notification_creation() {
601 let notification = JsonRpcNotification::new("event", json!({"data": "value"}));
602
603 assert_eq!(notification.method, "event");
604 assert!(notification.has_params());
605 }
606
607 #[test]
608 fn test_json_rpc_error_types() {
609 let parse_error = JsonRpcError::parse_error();
610 assert_eq!(parse_error.code, -32700);
611 assert!(parse_error.is_standard_error());
612
613 let app_error = JsonRpcError::application_error(-32000, "App error", "Details");
614 assert_eq!(app_error.code, -32000);
615 assert!(app_error.is_application_error());
616 }
617
618 #[test]
619 fn test_request_id_variants() {
620 let string_id = RequestId::from("test");
621 let number_id = RequestId::from(42i64);
622 let null_id = RequestId::Null;
623
624 assert_eq!(string_id.to_string(), "test");
625 assert_eq!(number_id.to_string(), "42");
626 assert_eq!(null_id.to_string(), "null");
627 }
628
629 #[test]
630 fn test_message_serialization() {
631 let request = JsonRpcRequest::new("1", "test", json!({}));
632 let json = serde_json::to_string(&request).unwrap();
633 let deserialized: JsonRpcRequest = serde_json::from_str(&json).unwrap();
634 assert_eq!(request, deserialized);
635 }
636
637 #[test]
638 fn test_generic_message_handling() {
639 let request = JsonRpcMessage::Request(JsonRpcRequest::new("1", "test", json!({})));
640 let notification =
641 JsonRpcMessage::Notification(JsonRpcNotification::new("event", json!({})));
642
643 assert_eq!(request.method(), Some("test"));
644 assert_eq!(notification.method(), Some("event"));
645
646 assert!(request.expects_response());
647 assert!(!notification.expects_response());
648 }
649}