1use serde::{Deserialize, Deserializer, Serialize};
2use serde_json::Value;
3
4use crate::{ErrorCodes, Notification, Request};
5
6pub(crate) fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
7where
8 T: Deserialize<'de>,
9 D: Deserializer<'de>,
10{
11 T::deserialize(deserializer).map(Some)
12}
13
14#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
15enum Version {
16 #[serde(rename = "2.0")]
17 TwoPointZero,
18}
19
20#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
22#[serde(untagged)]
23pub enum Id {
24 Number(i64),
26 String(String),
28 Null,
35}
36
37impl From<i64> for Id {
38 fn from(value: i64) -> Self {
39 Self::Number(value)
40 }
41}
42
43impl From<i32> for Id {
44 fn from(value: i32) -> Self {
45 Self::Number(value as i64)
46 }
47}
48
49impl From<String> for Id {
50 fn from(value: String) -> Self {
51 Self::String(value)
52 }
53}
54
55impl From<()> for Id {
56 fn from((): ()) -> Self {
57 Self::Null
58 }
59}
60
61impl From<crate::Id> for Id {
62 fn from(value: crate::Id) -> Self {
63 match value {
64 crate::Id::Int(int) => Self::Number(int as i64),
65 crate::Id::String(string) => Self::String(string),
66 }
67 }
68}
69
70impl TryFrom<Id> for crate::Id {
71 type Error = String;
72
73 fn try_from(value: Id) -> Result<Self, Self::Error> {
74 match value {
75 Id::String(string) => Ok(Self::String(string)),
76 Id::Number(number) => Ok(Self::Int(
77 i32::try_from(number).map_err(|e| format!("Request ID int too big: {e}"))?,
78 )),
79 Id::Null => Err(Self::Error::from("Id cannot be null")),
80 }
81 }
82}
83
84#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Eq)]
86pub struct RequestObject {
87 jsonrpc: Version,
89 #[serde(default, deserialize_with = "deserialize_some")]
93 #[serde(skip_serializing_if = "Option::is_none")]
94 id: Option<Id>,
95 #[serde(default)]
99 method: String,
100 #[serde(default, deserialize_with = "deserialize_some")]
106 #[serde(skip_serializing_if = "Option::is_none")]
107 params: Option<Value>,
108}
109
110impl RequestObject {
111 pub fn from_request<R>(id: Id, params: R::Params) -> Self
118 where
119 R: Request,
120 {
121 let params = serde_json::to_value(params).expect("Invalid request params");
122 let params = match params {
123 Value::Null => None,
124 Value::Array(_) | Value::Object(_) => Some(params),
125 _ => panic!("Parameters must be an object or array, if not omitted."),
126 };
127 Self {
128 jsonrpc: Version::TwoPointZero,
129 id: Some(id),
130 params,
131 method: R::METHOD.into(),
132 }
133 }
134
135 pub fn from_notification<N>(params: N::Params) -> Self
142 where
143 N: Notification,
144 {
145 let params = serde_json::to_value(params).expect("Invalid request params");
146 let params = match params {
147 Value::Null => None,
148 Value::Array(_) | Value::Object(_) => Some(params),
149 _ => panic!("Parameters must be an object or array, if not omitted."),
150 };
151 Self {
152 jsonrpc: Version::TwoPointZero,
153 method: N::METHOD.to_string(),
154 params,
155 id: None,
156 }
157 }
158
159 #[must_use]
161 pub fn method(&self) -> &str {
162 self.method.as_ref()
163 }
164
165 #[must_use]
167 pub const fn id(&self) -> Option<&Id> {
168 self.id.as_ref()
169 }
170
171 #[must_use]
173 pub const fn params(&self) -> Option<&Value> {
174 self.params.as_ref()
175 }
176
177 #[must_use]
179 pub fn into_parts(self) -> (String, Option<Id>, Option<Value>) {
180 (self.method, self.id, self.params)
181 }
182}
183
184#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
185#[serde(untagged)]
186enum Kind {
187 Ok { result: Value },
191 Err { error: Error },
194}
195
196#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
198pub struct Error {
199 pub code: ErrorCodes,
201 pub message: String,
204 #[serde(skip_serializing_if = "Option::is_none")]
208 pub data: Option<Value>,
209}
210
211#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
213pub struct ResponseObject {
214 jsonrpc: Version,
216 #[serde(flatten)]
217 kind: Kind,
218 id: Id,
222}
223
224impl ResponseObject {
225 pub fn from_success<R>(id: Id, result: R::Result) -> Self
232 where
233 R: Request,
234 {
235 let result = serde_json::to_value(result).unwrap();
236 Self {
237 jsonrpc: Version::TwoPointZero,
238 kind: Kind::Ok { result },
239 id,
240 }
241 }
242
243 #[must_use]
245 pub const fn from_error(id: Id, error: Error) -> Self {
246 Self {
247 jsonrpc: Version::TwoPointZero,
248 kind: Kind::Err { error },
249 id,
250 }
251 }
252
253 #[must_use]
255 pub const fn is_ok(&self) -> bool {
256 matches!(self.kind, Kind::Ok { .. })
257 }
258
259 #[must_use]
261 pub const fn is_error(&self) -> bool {
262 !self.is_ok()
263 }
264
265 #[must_use]
267 pub const fn id(&self) -> &Id {
268 &self.id
269 }
270
271 #[must_use]
273 pub const fn result(&self) -> Option<&Value> {
274 match &self.kind {
275 Kind::Ok { result } => Some(result),
276 Kind::Err { .. } => None,
277 }
278 }
279
280 #[must_use]
282 pub const fn error(&self) -> Option<&Error> {
283 match &self.kind {
284 Kind::Err { error } => Some(error),
285 Kind::Ok { .. } => None,
286 }
287 }
288}