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;
90pub const INVALID_REQUEST: i32 = -32600;
91pub const METHOD_NOT_FOUND: i32 = -32601;
92pub const INVALID_PARAMS: i32 = -32602;
93pub const INTERNAL_ERROR: i32 = -32603;
94
95pub fn ok(id: Option<RpcId>, result: Box<RawValue>) -> RpcResponse {
97 RpcResponse {
98 jsonrpc: "2.0".to_string(),
99 id,
100 result: Some(result),
101 error: None,
102 partial: None,
103 }
104}
105
106pub fn err(id: Option<RpcId>, code: i32, message: String, data: Option<Value>) -> RpcResponse {
108 RpcResponse {
109 jsonrpc: "2.0".to_string(),
110 id,
111 result: None,
112 error: Some(RpcError {
113 code,
114 message,
115 data,
116 }),
117 partial: None,
118 }
119}
120
121pub fn ok_partial(id: Option<RpcId>, result: Box<RawValue>) -> RpcResponse {
123 RpcResponse {
124 jsonrpc: "2.0".to_string(),
125 id,
126 result: Some(result),
127 error: None,
128 partial: Some(true),
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use serde_json::json;
136
137 #[test]
138 fn test_rpc_id_serialization() {
139 let id = RpcId::Number(42);
140 let json = serde_json::to_string(&id).unwrap();
141 assert_eq!(json, "42");
142 let parsed: RpcId = serde_json::from_str(&json).unwrap();
143 assert_eq!(parsed, id);
144
145 let id = RpcId::String("abc-123".to_string());
146 let json = serde_json::to_string(&id).unwrap();
147 assert_eq!(json, r#""abc-123""#);
148 let parsed: RpcId = serde_json::from_str(&json).unwrap();
149 assert_eq!(parsed, id);
150
151 let id = RpcId::Null;
152 let json = serde_json::to_string(&id).unwrap();
153 assert_eq!(json, "null");
154 let parsed: RpcId = serde_json::from_str(&json).unwrap();
155 assert_eq!(parsed, id);
156 }
157
158 #[test]
159 fn test_request_serialization() {
160 let request = RpcRequest {
161 jsonrpc: "2.0".to_string(),
162 id: Some(RpcId::Number(1)),
163 method: "test.method".to_string(),
164 params: json!({"key": "value"}),
165 };
166
167 let json = serde_json::to_value(&request).unwrap();
168 assert_eq!(json["jsonrpc"], "2.0");
169 assert_eq!(json["id"], 1);
170 assert_eq!(json["method"], "test.method");
171 assert_eq!(json["params"]["key"], "value");
172
173 let parsed: RpcRequest = serde_json::from_value(json).unwrap();
174 assert_eq!(parsed.jsonrpc, "2.0");
175 assert_eq!(parsed.id, Some(RpcId::Number(1)));
176 assert_eq!(parsed.method, "test.method");
177 }
178
179 #[test]
180 fn test_response_ok() {
181 let raw = serde_json::value::to_raw_value(&json!({"status": "ok"})).unwrap();
182 let response = ok(Some(RpcId::Number(1)), raw);
183
184 assert_eq!(response.jsonrpc, "2.0");
185 assert_eq!(response.id, Some(RpcId::Number(1)));
186 assert!(response.result.is_some());
187 assert!(response.error.is_none());
188
189 let serialized = serde_json::to_string(&response).unwrap();
190 let json: serde_json::Value = serde_json::from_str(&serialized).unwrap();
191 assert_eq!(json["result"]["status"], "ok");
192 assert!(json.get("error").is_none());
193 }
194
195 #[test]
196 fn test_response_error() {
197 let response = err(
198 Some(RpcId::Number(2)),
199 METHOD_NOT_FOUND,
200 "Method not found".to_string(),
201 Some(json!({"method": "unknown.method"})),
202 );
203
204 assert_eq!(response.jsonrpc, "2.0");
205 assert_eq!(response.id, Some(RpcId::Number(2)));
206 assert!(response.result.is_none());
207 assert!(response.error.is_some());
208
209 let error = response.error.unwrap();
210 assert_eq!(error.code, METHOD_NOT_FOUND);
211 assert_eq!(error.message, "Method not found");
212 assert_eq!(error.data.unwrap()["method"], "unknown.method");
213 }
214
215 #[test]
216 fn test_notification_no_id() {
217 let request = RpcRequest {
218 jsonrpc: "2.0".to_string(),
219 id: None,
220 method: "notification".to_string(),
221 params: json!(null),
222 };
223
224 let json = serde_json::to_value(&request).unwrap();
225 assert!(json["id"].is_null() || !json.as_object().unwrap().contains_key("id"));
226 }
227}