1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Deserialize)]
8pub struct Request {
9 #[serde(default)]
11 pub id: Option<Value>,
12 pub method: String,
14 #[serde(default)]
16 pub params: Value,
17}
18
19impl Request {
20 pub fn is_notification(&self) -> bool {
22 self.id.is_none()
23 }
24}
25
26#[derive(Debug, Serialize)]
28pub struct Response {
29 pub jsonrpc: &'static str,
31 pub id: Value,
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub result: Option<Value>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub error: Option<RpcError>,
39}
40
41#[derive(Debug, Serialize)]
43pub struct RpcError {
44 pub code: i64,
46 pub message: String,
48}
49
50impl Response {
51 pub fn ok(id: Value, result: Value) -> Self {
53 Response {
54 jsonrpc: "2.0",
55 id,
56 result: Some(result),
57 error: None,
58 }
59 }
60 pub fn err(id: Value, code: i64, message: &str) -> Self {
62 Response {
63 jsonrpc: "2.0",
64 id,
65 result: None,
66 error: Some(RpcError {
67 code,
68 message: message.into(),
69 }),
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use serde_json::json;
78
79 #[test]
80 fn parses_request_with_id() {
81 let r: Request = serde_json::from_value(json!({
82 "jsonrpc":"2.0","id":1,"method":"tools/list","params":{}
83 }))
84 .unwrap();
85 assert_eq!(r.method, "tools/list");
86 assert!(!r.is_notification());
87 }
88
89 #[test]
90 fn parses_notification_without_id() {
91 let r: Request = serde_json::from_value(json!({
92 "jsonrpc":"2.0","method":"notifications/initialized"
93 }))
94 .unwrap();
95 assert!(r.is_notification());
96 }
97
98 #[test]
99 fn ok_response_omits_error() {
100 let v = serde_json::to_value(Response::ok(json!(1), json!({"ok":true}))).unwrap();
101 assert_eq!(v, json!({"jsonrpc":"2.0","id":1,"result":{"ok":true}}));
102 }
103
104 #[test]
105 fn err_response_omits_result() {
106 let v = serde_json::to_value(Response::err(json!(2), -32601, "method not found")).unwrap();
107 assert_eq!(
108 v,
109 json!({"jsonrpc":"2.0","id":2,"error":{"code":-32601,"message":"method not found"}})
110 );
111 }
112}