1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::fmt;
4
5#[derive(Debug, Deserialize)]
6pub struct Request {
7 pub jsonrpc: String,
8 pub method: String,
9 #[serde(default)]
10 pub params: Value,
11 pub id: Option<Value>,
12}
13
14#[derive(Debug, Serialize)]
15pub struct Response {
16 pub jsonrpc: String,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub result: Option<Value>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub error: Option<Error>,
21 pub id: Option<Value>,
22}
23
24#[derive(Debug, Serialize)]
25pub struct Error {
26 pub code: i32,
27 pub message: String,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub data: Option<Value>,
30}
31
32pub mod error_codes {
34 pub const PARSE_ERROR: i32 = -32700;
35 pub const INVALID_REQUEST: i32 = -32600;
36 pub const METHOD_NOT_FOUND: i32 = -32601;
37 pub const INVALID_PARAMS: i32 = -32602;
38 pub const INTERNAL_ERROR: i32 = -32603;
39 }
41
42impl Response {
43 pub fn success(result: Value, id: Option<Value>) -> Self {
44 Self {
45 jsonrpc: "2.0".to_string(),
46 result: Some(result),
47 error: None,
48 id,
49 }
50 }
51
52 pub fn error(code: i32, message: String, id: Option<Value>) -> Self {
53 Self {
54 jsonrpc: "2.0".to_string(),
55 result: None,
56 error: Some(Error {
57 code,
58 message,
59 data: None,
60 }),
61 id,
62 }
63 }
64
65 pub fn to_string(&self) -> Result<String, String> {
66 serde_json::to_string(self).map_err(|e| format!("Failed to serialize response: {}", e))
67 }
68}
69
70pub fn success(result: Value, id: Option<Value>) -> Result<String, String> {
72 Response::success(result, id).to_string()
73}
74
75pub fn error(code: i32, message: &str, id: Option<Value>) -> Result<String, String> {
76 Response::error(code, message.to_string(), id).to_string()
77}
78
79pub fn parse_request(message: &str) -> Result<Request, String> {
80 let trimmed = message.trim();
82 if trimmed.is_empty() {
83 return Err("Empty JSON-RPC message".to_string());
84 }
85
86 match serde_json::from_str::<Request>(trimmed) {
88 Ok(request) => {
89 if request.jsonrpc != "2.0" {
91 return Err(format!("Invalid JSON-RPC version: {}", request.jsonrpc));
92 }
93
94 if request.method.is_empty() {
96 return Err("Method cannot be empty".to_string());
97 }
98
99 Ok(request)
100 },
101 Err(e) => {
102 let error_msg = match e.classify() {
104 serde_json::error::Category::Io => "I/O error while reading JSON",
105 serde_json::error::Category::Syntax => "JSON syntax error",
106 serde_json::error::Category::Data => "JSON data error (missing or invalid fields)",
107 serde_json::error::Category::Eof => "Unexpected end of JSON input",
108 };
109
110 Err(format!("Invalid JSON-RPC message: {} - {}", error_msg, e))
111 }
112 }
113}
114
115#[derive(Debug)]
117pub struct JsonRpcError {
118 pub code: i32,
119 pub message: String,
120 pub id: Option<Value>,
121}
122
123impl fmt::Display for JsonRpcError {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(f, "JSON-RPC Error {}: {}", self.code, self.message)
126 }
127}
128
129impl std::error::Error for JsonRpcError {}
130
131impl From<JsonRpcError> for Response {
133 fn from(err: JsonRpcError) -> Self {
134 Response::error(err.code, err.message, err.id)
135 }
136}