1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::protocol::{constants::JSONRPC_VERSION_FIELD, error::ErrorData};
5
6#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
7#[serde(untagged, try_from = "JsonRpcRaw")]
8pub enum JsonRpcMessage {
9 Request(JsonRpcRequest),
10 Response(JsonRpcResponse),
11 Notification(JsonRpcNotification),
12 Error(JsonRpcError),
13 Nil, }
15
16#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
17pub struct JsonRpcRequest {
18 pub jsonrpc: String,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub id: Option<u64>,
21 pub method: String,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub params: Option<Value>,
24}
25
26impl JsonRpcRequest {
27 pub fn new(id: Option<u64>, method: impl Into<String>, params: Option<Value>) -> Self {
28 Self {
29 jsonrpc: JSONRPC_VERSION_FIELD.to_string(),
30 id,
31 method: method.into(),
32 params,
33 }
34 }
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
38pub struct JsonRpcResponse {
39 pub jsonrpc: String,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub id: Option<u64>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub result: Option<Value>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub error: Option<ErrorData>,
46}
47
48impl JsonRpcResponse {
49 pub fn empty(id: Option<u64>) -> Self {
50 Self {
51 jsonrpc: JSONRPC_VERSION_FIELD.to_string(),
52 id,
53 result: None,
54 error: None,
55 }
56 }
57
58 pub fn error(id: Option<u64>, error: ErrorData) -> Self {
59 Self {
60 jsonrpc: JSONRPC_VERSION_FIELD.to_string(),
61 id,
62 result: None,
63 error: Some(error),
64 }
65 }
66
67 pub fn success(id: Option<u64>, result: Value) -> Self {
68 Self {
69 jsonrpc: JSONRPC_VERSION_FIELD.to_string(),
70 id,
71 result: Some(result),
72 error: None,
73 }
74 }
75}
76
77#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
78pub struct JsonRpcNotification {
79 pub jsonrpc: String,
80 pub method: String,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub params: Option<Value>,
83}
84
85#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
86pub struct JsonRpcError {
87 pub jsonrpc: String,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub id: Option<u64>,
90 pub error: ErrorData,
91}
92
93#[derive(Debug, Serialize, Deserialize)]
94pub struct JsonRpcRaw {
95 pub jsonrpc: String,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub id: Option<u64>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub method: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub params: Option<Value>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub result: Option<Value>,
104 #[serde(skip_serializing_if = "Option::is_none")]
105 pub error: Option<ErrorData>,
106}
107
108impl TryFrom<JsonRpcRaw> for JsonRpcMessage {
109 type Error = String;
110
111 fn try_from(raw: JsonRpcRaw) -> Result<Self, <Self as TryFrom<JsonRpcRaw>>::Error> {
112 if raw.error.is_some() {
114 return Ok(JsonRpcMessage::Error(JsonRpcError {
115 jsonrpc: raw.jsonrpc,
116 id: raw.id,
117 error: raw.error.unwrap(),
118 }));
119 }
120
121 if raw.result.is_some() {
123 return Ok(JsonRpcMessage::Response(JsonRpcResponse {
124 jsonrpc: raw.jsonrpc,
125 id: raw.id,
126 result: raw.result,
127 error: None,
128 }));
129 }
130
131 if let Some(method) = raw.method {
133 if raw.id.is_none() {
134 return Ok(JsonRpcMessage::Notification(JsonRpcNotification {
135 jsonrpc: raw.jsonrpc,
136 method,
137 params: raw.params,
138 }));
139 }
140
141 return Ok(JsonRpcMessage::Request(JsonRpcRequest {
142 jsonrpc: raw.jsonrpc,
143 id: raw.id,
144 method,
145 params: raw.params,
146 }));
147 }
148
149 if raw.id.is_none() && raw.result.is_none() && raw.error.is_none() {
151 return Ok(JsonRpcMessage::Nil);
152 }
153
154 Err(format!(
156 "Invalid JSON-RPC message format: id={:?}, method={:?}, result={:?}, error={:?}",
157 raw.id, raw.method, raw.result, raw.error
158 ))
159 }
160}