1use crate::error::JsonRpcError;
29use serde::{Deserialize, Serialize};
30use std::borrow::Cow;
31
32pub const JSONRPC_VERSION: &str = "2.0";
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
40#[serde(untagged)]
41pub enum RequestId {
42 Number(u64),
44 String(String),
46}
47
48impl RequestId {
49 #[must_use]
51 pub const fn number(id: u64) -> Self {
52 Self::Number(id)
53 }
54
55 #[must_use]
57 pub fn string(id: impl Into<String>) -> Self {
58 Self::String(id.into())
59 }
60}
61
62impl From<u64> for RequestId {
63 fn from(id: u64) -> Self {
64 Self::Number(id)
65 }
66}
67
68impl From<String> for RequestId {
69 fn from(id: String) -> Self {
70 Self::String(id)
71 }
72}
73
74impl From<&str> for RequestId {
75 fn from(id: &str) -> Self {
76 Self::String(id.to_string())
77 }
78}
79
80impl std::fmt::Display for RequestId {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 match self {
83 Self::Number(n) => write!(f, "{n}"),
84 Self::String(s) => write!(f, "{s}"),
85 }
86 }
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct Request {
95 pub jsonrpc: Cow<'static, str>,
97 pub id: RequestId,
99 pub method: Cow<'static, str>,
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub params: Option<serde_json::Value>,
104}
105
106impl Request {
107 #[must_use]
109 pub fn new(method: impl Into<Cow<'static, str>>, id: impl Into<RequestId>) -> Self {
110 Self {
111 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
112 id: id.into(),
113 method: method.into(),
114 params: None,
115 }
116 }
117
118 #[must_use]
120 pub fn with_params(
121 method: impl Into<Cow<'static, str>>,
122 id: impl Into<RequestId>,
123 params: serde_json::Value,
124 ) -> Self {
125 Self {
126 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
127 id: id.into(),
128 method: method.into(),
129 params: Some(params),
130 }
131 }
132
133 #[must_use]
135 pub fn params(mut self, params: serde_json::Value) -> Self {
136 self.params = Some(params);
137 self
138 }
139
140 #[must_use]
142 pub fn method(&self) -> &str {
143 &self.method
144 }
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct Response {
153 pub jsonrpc: Cow<'static, str>,
155 pub id: RequestId,
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub result: Option<serde_json::Value>,
160 #[serde(skip_serializing_if = "Option::is_none")]
162 pub error: Option<JsonRpcError>,
163}
164
165impl Response {
166 #[must_use]
168 pub fn success(id: impl Into<RequestId>, result: serde_json::Value) -> Self {
169 Self {
170 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
171 id: id.into(),
172 result: Some(result),
173 error: None,
174 }
175 }
176
177 #[must_use]
179 pub fn error(id: impl Into<RequestId>, error: JsonRpcError) -> Self {
180 Self {
181 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
182 id: id.into(),
183 result: None,
184 error: Some(error),
185 }
186 }
187
188 #[must_use]
190 pub const fn is_success(&self) -> bool {
191 self.result.is_some() && self.error.is_none()
192 }
193
194 #[must_use]
196 pub const fn is_error(&self) -> bool {
197 self.error.is_some()
198 }
199
200 pub fn into_result(self) -> Result<serde_json::Value, JsonRpcError> {
204 if let Some(error) = self.error {
205 Err(error)
206 } else {
207 self.result.ok_or_else(|| JsonRpcError {
208 code: -32603,
209 message: "Response contained neither result nor error".to_string(),
210 data: None,
211 })
212 }
213 }
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct Notification {
222 pub jsonrpc: Cow<'static, str>,
224 pub method: Cow<'static, str>,
226 #[serde(skip_serializing_if = "Option::is_none")]
228 pub params: Option<serde_json::Value>,
229}
230
231impl Notification {
232 #[must_use]
234 pub fn new(method: impl Into<Cow<'static, str>>) -> Self {
235 Self {
236 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
237 method: method.into(),
238 params: None,
239 }
240 }
241
242 #[must_use]
244 pub fn with_params(method: impl Into<Cow<'static, str>>, params: serde_json::Value) -> Self {
245 Self {
246 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
247 method: method.into(),
248 params: Some(params),
249 }
250 }
251
252 #[must_use]
254 pub fn params(mut self, params: serde_json::Value) -> Self {
255 self.params = Some(params);
256 self
257 }
258
259 #[must_use]
261 pub fn method(&self) -> &str {
262 &self.method
263 }
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize)]
271#[serde(untagged)]
272pub enum Message {
273 Request(Request),
275 Response(Response),
277 Notification(Notification),
279}
280
281impl Message {
282 #[must_use]
284 pub fn method(&self) -> Option<&str> {
285 match self {
286 Self::Request(r) => Some(&r.method),
287 Self::Notification(n) => Some(&n.method),
288 Self::Response(_) => None,
289 }
290 }
291
292 #[must_use]
294 pub const fn id(&self) -> Option<&RequestId> {
295 match self {
296 Self::Request(r) => Some(&r.id),
297 Self::Response(r) => Some(&r.id),
298 Self::Notification(_) => None,
299 }
300 }
301
302 #[must_use]
304 pub const fn is_request(&self) -> bool {
305 matches!(self, Self::Request(_))
306 }
307
308 #[must_use]
310 pub const fn is_response(&self) -> bool {
311 matches!(self, Self::Response(_))
312 }
313
314 #[must_use]
316 pub const fn is_notification(&self) -> bool {
317 matches!(self, Self::Notification(_))
318 }
319
320 #[must_use]
322 pub const fn as_request(&self) -> Option<&Request> {
323 match self {
324 Self::Request(r) => Some(r),
325 _ => None,
326 }
327 }
328
329 #[must_use]
331 pub const fn as_response(&self) -> Option<&Response> {
332 match self {
333 Self::Response(r) => Some(r),
334 _ => None,
335 }
336 }
337
338 #[must_use]
340 pub const fn as_notification(&self) -> Option<&Notification> {
341 match self {
342 Self::Notification(n) => Some(n),
343 _ => None,
344 }
345 }
346}
347
348impl From<Request> for Message {
349 fn from(r: Request) -> Self {
350 Self::Request(r)
351 }
352}
353
354impl From<Response> for Message {
355 fn from(r: Response) -> Self {
356 Self::Response(r)
357 }
358}
359
360impl From<Notification> for Message {
361 fn from(n: Notification) -> Self {
362 Self::Notification(n)
363 }
364}
365
366#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
371#[serde(untagged)]
372pub enum ProgressToken {
373 Number(u64),
375 String(String),
377}
378
379impl std::fmt::Display for ProgressToken {
380 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
381 match self {
382 Self::Number(n) => write!(f, "{n}"),
383 Self::String(s) => write!(f, "{s}"),
384 }
385 }
386}
387
388#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
393#[serde(transparent)]
394pub struct Cursor(pub String);
395
396impl Cursor {
397 #[must_use]
399 pub fn new(cursor: impl Into<String>) -> Self {
400 Self(cursor.into())
401 }
402}
403
404impl std::fmt::Display for Cursor {
405 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
406 write!(f, "{}", self.0)
407 }
408}
409
410impl From<String> for Cursor {
411 fn from(s: String) -> Self {
412 Self(s)
413 }
414}
415
416impl From<&str> for Cursor {
417 fn from(s: &str) -> Self {
418 Self(s.to_string())
419 }
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425
426 #[test]
427 fn test_request_serialization() {
428 let request = Request::new("tools/list", 1u64);
429 let json = serde_json::to_string(&request).unwrap();
430 assert!(json.contains("\"jsonrpc\":\"2.0\""));
431 assert!(json.contains("\"method\":\"tools/list\""));
432 assert!(json.contains("\"id\":1"));
433 }
434
435 #[test]
436 fn test_request_with_params() {
437 let request = Request::with_params(
438 "tools/call",
439 1u64,
440 serde_json::json!({"name": "search", "arguments": {"query": "test"}}),
441 );
442 let json = serde_json::to_string(&request).unwrap();
443 assert!(json.contains("\"params\""));
444 assert!(json.contains("\"name\":\"search\""));
445 }
446
447 #[test]
448 fn test_response_success() {
449 let response = Response::success(1u64, serde_json::json!({"tools": []}));
450 assert!(response.is_success());
451 assert!(!response.is_error());
452
453 let result = response.into_result().unwrap();
454 assert!(result.get("tools").is_some());
455 }
456
457 #[test]
458 fn test_response_error() {
459 let error = JsonRpcError {
460 code: -32601,
461 message: "Method not found".to_string(),
462 data: None,
463 };
464 let response = Response::error(1u64, error);
465 assert!(!response.is_success());
466 assert!(response.is_error());
467
468 let err = response.into_result().unwrap_err();
469 assert_eq!(err.code, -32601);
470 }
471
472 #[test]
473 fn test_notification() {
474 let notification = Notification::with_params(
475 "notifications/progress",
476 serde_json::json!({"progress": 50, "total": 100}),
477 );
478 let json = serde_json::to_string(¬ification).unwrap();
479 assert!(json.contains("\"method\":\"notifications/progress\""));
480 assert!(!json.contains("\"id\"")); }
482
483 #[test]
484 fn test_message_parsing() {
485 let json = r#"{"jsonrpc":"2.0","id":1,"method":"test"}"#;
487 let msg: Message = serde_json::from_str(json).unwrap();
488 assert!(msg.is_request());
489 assert_eq!(msg.method(), Some("test"));
490
491 let json = r#"{"jsonrpc":"2.0","id":1,"result":{}}"#;
493 let msg: Message = serde_json::from_str(json).unwrap();
494 assert!(msg.is_response());
495
496 let json = r#"{"jsonrpc":"2.0","method":"notify"}"#;
498 let msg: Message = serde_json::from_str(json).unwrap();
499 assert!(msg.is_notification());
500 }
501
502 #[test]
503 fn test_request_id_types() {
504 let request = Request::new("test", 42u64);
506 let json = serde_json::to_string(&request).unwrap();
507 assert!(json.contains("\"id\":42"));
508
509 let request = Request::new("test", "req-001");
511 let json = serde_json::to_string(&request).unwrap();
512 assert!(json.contains("\"id\":\"req-001\""));
513 }
514}