cuprate_json_rpc/response.rs
1//! JSON-RPC 2.0 response object.
2
3//---------------------------------------------------------------------------------------------------- Use
4use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
5
6use crate::{error::ErrorObject, id::Id, version::Version};
7
8//---------------------------------------------------------------------------------------------------- Response
9/// [The response object](https://www.jsonrpc.org/specification#response_object).
10///
11/// The generic `T` is the response payload, i.e. it is the
12/// type that holds both the `method` and `params`.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct Response<T> {
15 /// JSON-RPC protocol version; always `2.0`.
16 pub jsonrpc: Version,
17
18 /// This field must always be present in serialized JSON.
19 ///
20 /// ### JSON-RPC 2.0 rules
21 /// - The [`Response`]'s ID must be the same as the [`Request`](crate::Request)
22 /// - If the `Request` omitted the `id` field, there should be no `Response`
23 /// - If there was an error in detecting the `Request`'s ID, the `Response` must contain an [`Id::Null`]
24 pub id: Id,
25
26 /// The response payload.
27 ///
28 /// ### JSON-RPC 2.0 rules
29 /// - This must be [`Ok`] upon success
30 /// - This must be [`Err`] upon error
31 /// - This can be any (de)serializable data `T` on success
32 /// - This must be [`ErrorObject`] on errors
33 pub payload: Result<T, ErrorObject>,
34}
35
36impl<T> Response<T> {
37 /// Creates a successful response.
38 ///
39 /// ```rust
40 /// use cuprate_json_rpc::{Id, Response};
41 ///
42 /// let ok = Response::ok(Id::Num(123), "OK");
43 /// let json = serde_json::to_string(&ok).unwrap();
44 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":123,"result":"OK"}"#);
45 /// ```
46 pub const fn ok(id: Id, result: T) -> Self {
47 Self {
48 jsonrpc: Version,
49 id,
50 payload: Ok(result),
51 }
52 }
53
54 /// Creates an error response.
55 ///
56 /// ```rust
57 /// use cuprate_json_rpc::{Id, Response, error::{ErrorObject, ErrorCode}};
58 ///
59 /// let err = ErrorObject {
60 /// code: 0.into(),
61 /// message: "m".into(),
62 /// data: Some("d".into()),
63 /// };
64 ///
65 /// let ok = Response::<()>::err(Id::Num(123), err);
66 /// let json = serde_json::to_string(&ok).unwrap();
67 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":123,"error":{"code":0,"message":"m","data":"d"}}"#);
68 /// ```
69 pub const fn err(id: Id, error: ErrorObject) -> Self {
70 Self {
71 jsonrpc: Version,
72 id,
73 payload: Err(error),
74 }
75 }
76
77 /// Creates an error response using [`ErrorObject::parse_error`].
78 ///
79 /// ```rust
80 /// use cuprate_json_rpc::{Id, Response, error::{ErrorObject, ErrorCode}};
81 ///
82 /// let ok = Response::<()>::parse_error(Id::Num(0));
83 /// let json = serde_json::to_string(&ok).unwrap();
84 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":0,"error":{"code":-32700,"message":"Parse error"}}"#);
85 /// ```
86 pub const fn parse_error(id: Id) -> Self {
87 Self {
88 jsonrpc: Version,
89 payload: Err(ErrorObject::parse_error()),
90 id,
91 }
92 }
93
94 /// Creates an error response using [`ErrorObject::invalid_request`].
95 ///
96 /// ```rust
97 /// use cuprate_json_rpc::{Id, Response, error::{ErrorObject, ErrorCode}};
98 ///
99 /// let ok = Response::<()>::invalid_request(Id::Num(0));
100 /// let json = serde_json::to_string(&ok).unwrap();
101 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":0,"error":{"code":-32600,"message":"Invalid Request"}}"#);
102 /// ```
103 pub const fn invalid_request(id: Id) -> Self {
104 Self {
105 jsonrpc: Version,
106 payload: Err(ErrorObject::invalid_request()),
107 id,
108 }
109 }
110
111 /// Creates an error response using [`ErrorObject::method_not_found`].
112 ///
113 /// ```rust
114 /// use cuprate_json_rpc::{Id, Response, error::{ErrorObject, ErrorCode}};
115 ///
116 /// let ok = Response::<()>::method_not_found(Id::Num(0));
117 /// let json = serde_json::to_string(&ok).unwrap();
118 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":0,"error":{"code":-32601,"message":"Method not found"}}"#);
119 /// ```
120 pub const fn method_not_found(id: Id) -> Self {
121 Self {
122 jsonrpc: Version,
123 payload: Err(ErrorObject::method_not_found()),
124 id,
125 }
126 }
127
128 /// Creates an error response using [`ErrorObject::invalid_params`].
129 ///
130 /// ```rust
131 /// use cuprate_json_rpc::{Id, Response, error::{ErrorObject, ErrorCode}};
132 ///
133 /// let ok = Response::<()>::invalid_params(Id::Num(0));
134 /// let json = serde_json::to_string(&ok).unwrap();
135 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":0,"error":{"code":-32602,"message":"Invalid params"}}"#);
136 /// ```
137 pub const fn invalid_params(id: Id) -> Self {
138 Self {
139 jsonrpc: Version,
140 payload: Err(ErrorObject::invalid_params()),
141 id,
142 }
143 }
144
145 /// Creates an error response using [`ErrorObject::internal_error`].
146 ///
147 /// ```rust
148 /// use cuprate_json_rpc::{Id, Response, error::{ErrorObject, ErrorCode}};
149 ///
150 /// let ok = Response::<()>::internal_error(Id::Num(0));
151 /// let json = serde_json::to_string(&ok).unwrap();
152 /// assert_eq!(json, r#"{"jsonrpc":"2.0","id":0,"error":{"code":-32603,"message":"Internal error"}}"#);
153 /// ```
154 pub const fn internal_error(id: Id) -> Self {
155 Self {
156 jsonrpc: Version,
157 payload: Err(ErrorObject::internal_error()),
158 id,
159 }
160 }
161}
162
163//---------------------------------------------------------------------------------------------------- Trait impl
164impl<T> std::fmt::Display for Response<T>
165where
166 T: Serialize,
167{
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 match serde_json::to_string_pretty(self) {
170 Ok(json) => write!(f, "{json}"),
171 Err(_) => Err(std::fmt::Error),
172 }
173 }
174}
175
176//---------------------------------------------------------------------------------------------------- Serde impl
177impl<T> Serialize for Response<T>
178where
179 T: Serialize,
180{
181 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
182 where
183 S: Serializer,
184 {
185 let mut s = serializer.serialize_struct("Response", 3)?;
186
187 s.serialize_field("jsonrpc", &self.jsonrpc)?;
188
189 // This member is required.
190 //
191 // Even if `null`, or the client `Request` didn't include one.
192 s.serialize_field("id", &self.id)?;
193
194 match &self.payload {
195 Ok(r) => s.serialize_field("result", r)?,
196 Err(e) => s.serialize_field("error", e)?,
197 }
198
199 s.end()
200 }
201}
202
203// [`Response`] has a manual deserialization implementation because
204// we need to confirm `result` and `error` don't both exist:
205//
206// > Either the result member or error member MUST be included, but both members MUST NOT be included.
207//
208// <https://www.jsonrpc.org/specification#error_object>
209impl<'de, T> Deserialize<'de> for Response<T>
210where
211 T: Deserialize<'de> + 'de,
212{
213 fn deserialize<D: Deserializer<'de>>(der: D) -> Result<Self, D::Error> {
214 use std::marker::PhantomData;
215
216 use serde::de::{Error, MapAccess, Visitor};
217
218 /// This type represents the key values within [`Response`].
219 enum Key {
220 /// "jsonrpc" field.
221 JsonRpc,
222 /// "result" field.
223 Result,
224 /// "error" field.
225 Error,
226 /// "id" field.
227 Id,
228 /// Any other unknown field (ignored).
229 Unknown,
230 }
231
232 // Deserialization for [`Response`]'s key fields.
233 //
234 // This ignores unknown keys.
235 impl<'de> Deserialize<'de> for Key {
236 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
237 where
238 D: Deserializer<'de>,
239 {
240 /// Serde visitor for [`Response`]'s key fields.
241 struct KeyVisitor;
242
243 impl Visitor<'_> for KeyVisitor {
244 type Value = Key;
245
246 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
247 formatter.write_str("`jsonrpc`, `id`, `result`, `error`")
248 }
249
250 fn visit_str<E>(self, string: &str) -> Result<Key, E>
251 where
252 E: Error,
253 {
254 // PERF: this match is in order of how this library serializes fields.
255 match string {
256 "jsonrpc" => Ok(Key::JsonRpc),
257 "id" => Ok(Key::Id),
258 "result" => Ok(Key::Result),
259 "error" => Ok(Key::Error),
260 // Ignore any other keys that appear
261 // and continue deserialization.
262 _ => Ok(Key::Unknown),
263 }
264 }
265 }
266
267 deserializer.deserialize_identifier(KeyVisitor)
268 }
269 }
270
271 /// Serde visitor for the key-value map of [`Response`].
272 struct MapVisit<T>(PhantomData<T>);
273
274 // Deserialization for [`Response`]'s key and values (the JSON map).
275 impl<'de, T> Visitor<'de> for MapVisit<T>
276 where
277 T: Deserialize<'de> + 'de,
278 {
279 type Value = Response<T>;
280
281 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
282 formatter.write_str("JSON-RPC 2.0 Response")
283 }
284
285 /// This is a loop that goes over every key-value pair
286 /// and fills out the necessary fields.
287 ///
288 /// If both `result/error` appear then this
289 /// deserialization will error, as to
290 /// follow the JSON-RPC 2.0 specification.
291 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
292 // Initialize values.
293 let mut jsonrpc = None;
294 let mut payload = None;
295 let mut id = None;
296
297 // Loop over map, filling values.
298 while let Some(key) = map.next_key::<Key>()? {
299 // PERF: this match is in order of how this library serializes fields.
300 match key {
301 Key::JsonRpc => jsonrpc = Some(map.next_value::<Version>()?),
302 Key::Id => id = Some(map.next_value::<Id>()?),
303 Key::Result => {
304 if payload.is_none() {
305 payload = Some(Ok(map.next_value::<T>()?));
306 } else {
307 return Err(Error::duplicate_field("result/error"));
308 }
309 }
310 Key::Error => {
311 if payload.is_none() {
312 payload = Some(Err(map.next_value::<ErrorObject>()?));
313 } else {
314 return Err(Error::duplicate_field("result/error"));
315 }
316 }
317 Key::Unknown => {
318 map.next_value::<serde::de::IgnoredAny>()?;
319 }
320 }
321 }
322
323 // Make sure all our key-value pairs are set and correct.
324 match (jsonrpc, id, payload) {
325 // Response with a single `result` or `error`.
326 (Some(jsonrpc), Some(id), Some(payload)) => Ok(Response {
327 jsonrpc,
328 id,
329 payload,
330 }),
331
332 // No fields existed.
333 (None, None, None) => Err(Error::missing_field("jsonrpc + id + result/error")),
334
335 // Some field was missing.
336 (None, _, _) => Err(Error::missing_field("jsonrpc")),
337 (_, None, _) => Err(Error::missing_field("id")),
338 (_, _, None) => Err(Error::missing_field("result/error")),
339 }
340 }
341 }
342
343 /// All expected fields of the [`Response`] type.
344 const FIELDS: &[&str; 4] = &["jsonrpc", "id", "result", "error"];
345 der.deserialize_struct("Response", FIELDS, MapVisit(PhantomData))
346 }
347}
348
349//---------------------------------------------------------------------------------------------------- TESTS
350#[cfg(test)]
351mod test {
352 use serde_json::json;
353
354 use super::*;
355 use crate::id::Id;
356
357 /// Basic serde test on OK results.
358 #[test]
359 fn serde_result() {
360 let result = String::from("result_ok");
361 let id = Id::Num(123);
362 let req = Response::ok(id.clone(), result.clone());
363
364 let ser: String = serde_json::to_string(&req).unwrap();
365 let de: Response<String> = serde_json::from_str(&ser).unwrap();
366
367 assert_eq!(de.payload.unwrap(), result);
368 assert_eq!(de.id, id);
369 }
370
371 /// Basic serde test on errors.
372 #[test]
373 fn serde_error() {
374 let error = ErrorObject::internal_error();
375 let id = Id::Num(123);
376 let req: Response<String> = Response::err(id.clone(), error.clone());
377
378 let ser: String = serde_json::to_string(&req).unwrap();
379 let de: Response<String> = serde_json::from_str(&ser).unwrap();
380
381 assert_eq!(de.payload.unwrap_err(), error);
382 assert_eq!(de.id, id);
383 }
384
385 /// Test that the `result` and `error` fields are mutually exclusive.
386 #[test]
387 #[should_panic(
388 expected = "called `Result::unwrap()` on an `Err` value: Error(\"duplicate field `result/error`\", line: 0, column: 0)"
389 )]
390 fn result_error_mutually_exclusive() {
391 let e = ErrorObject::internal_error();
392 let j = json!({
393 "jsonrpc": "2.0",
394 "id": 0,
395 "result": "",
396 "error": e
397 });
398 serde_json::from_value::<Response<String>>(j).unwrap();
399 }
400
401 /// Test that the `result` and `error` fields can repeat (and get overwritten).
402 #[test]
403 #[should_panic(
404 expected = "called `Result::unwrap()` on an `Err` value: Error(\"duplicate field `result/error`\", line: 1, column: 45)"
405 )]
406 fn result_repeat() {
407 // `result`
408 let json = r#"{"jsonrpc":"2.0","id":0,"result":"a","result":"b"}"#;
409 serde_json::from_str::<Response<String>>(json).unwrap();
410 }
411
412 /// Test that the `error` field cannot repeat.
413 #[test]
414 #[should_panic(
415 expected = "called `Result::unwrap()` on an `Err` value: Error(\"duplicate field `result/error`\", line: 1, column: 83)"
416 )]
417 fn error_repeat() {
418 let e = ErrorObject::invalid_request();
419 let e = serde_json::to_string(&e).unwrap();
420 let json = format!(r#"{{"jsonrpc":"2.0","id":0,"error":{e},"error":{e}}}"#);
421 serde_json::from_str::<Response<String>>(&json).unwrap();
422 }
423
424 /// Test that the `id` field must exist.
425 #[test]
426 #[should_panic(
427 expected = "called `Result::unwrap()` on an `Err` value: Error(\"missing field `id`\", line: 0, column: 0)"
428 )]
429 fn id_must_exist() {
430 let j = json!({
431 "jsonrpc": "2.0",
432 "result": "",
433 });
434 serde_json::from_value::<Response<String>>(j).unwrap();
435 }
436
437 /// Tests that non-ordered fields still deserialize okay.
438 #[test]
439 fn deserialize_out_of_order_keys() {
440 let e = ErrorObject::internal_error();
441 let j = json!({
442 "error": e,
443 "id": 0,
444 "jsonrpc": "2.0"
445 });
446 let resp = serde_json::from_value::<Response<String>>(j).unwrap();
447 assert_eq!(resp, Response::internal_error(Id::Num(0)));
448
449 let ok = Response::ok(Id::Num(0), "OK".to_string());
450 let j = json!({
451 "result": "OK",
452 "id": 0,
453 "jsonrpc": "2.0"
454 });
455 let resp = serde_json::from_value::<Response<String>>(j).unwrap();
456 assert_eq!(resp, ok);
457 }
458
459 /// Asserts that fields must be `lowercase`.
460 #[test]
461 #[should_panic(
462 expected = "called `Result::unwrap()` on an `Err` value: Error(\"missing field `jsonrpc`\", line: 1, column: 40)"
463 )]
464 fn lowercase() {
465 let mixed_case = r#"{"jSoNRPC":"2.0","id":123,"result":"OK"}"#;
466 serde_json::from_str::<Response<String>>(mixed_case).unwrap();
467 }
468
469 /// Tests that unknown fields are ignored, and deserialize continues.
470 /// Also that unicode and backslashes work.
471 #[test]
472 fn unknown_fields_and_unicode() {
473 let e = ErrorObject::internal_error();
474 let j = json!({
475 "error": e,
476 "\u{00f8}": 123,
477 "id": 0,
478 "unknown_field": 123,
479 "jsonrpc": "2.0",
480 "unknown_field": 123
481 });
482 let resp = serde_json::from_value::<Response<String>>(j).unwrap();
483 assert_eq!(resp, Response::internal_error(Id::Num(0)));
484 }
485}