jsonrpsee_types/
response.rs

1// Copyright 2019-2021 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any
4// person obtaining a copy of this software and associated
5// documentation files (the "Software"), to deal in the
6// Software without restriction, including without
7// limitation the rights to use, copy, modify, merge,
8// publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software
10// is furnished to do so, subject to the following
11// conditions:
12//
13// The above copyright notice and this permission notice
14// shall be included in all copies or substantial portions
15// of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25// DEALINGS IN THE SOFTWARE.
26
27//! Types pertaining to JSON-RPC responses.
28
29use std::borrow::Cow as StdCow;
30use std::fmt;
31use std::marker::PhantomData;
32
33use crate::error::ErrorCode;
34use crate::params::{Id, SubscriptionId, TwoPointZero};
35use crate::request::Notification;
36use crate::{ErrorObject, ErrorObjectOwned};
37use serde::ser::SerializeStruct;
38use serde::{Deserialize, Deserializer, Serialize, Serializer};
39
40/// JSON-RPC response object as defined in the [spec](https://www.jsonrpc.org/specification#response_object).
41pub struct Response<'a, T: Clone> {
42	/// JSON-RPC version.
43	pub jsonrpc: Option<TwoPointZero>,
44	/// Payload which can be result or error.
45	pub payload: ResponsePayload<'a, T>,
46	/// Request ID
47	pub id: Id<'a>,
48}
49
50impl<'a, T: Clone> Response<'a, T> {
51	/// Create a new [`Response`].
52	pub fn new(payload: ResponsePayload<'a, T>, id: Id<'a>) -> Response<'a, T> {
53		Response { jsonrpc: Some(TwoPointZero), payload, id }
54	}
55
56	/// Create an owned [`Response`].
57	pub fn into_owned(self) -> Response<'static, T> {
58		Response { jsonrpc: self.jsonrpc, payload: self.payload.into_owned(), id: self.id.into_owned() }
59	}
60}
61
62impl<'a, T> fmt::Display for Response<'a, T>
63where
64	T: Serialize + Clone,
65{
66	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67		f.write_str(&serde_json::to_string(&self).expect("valid JSON; qed"))
68	}
69}
70
71impl<'a, T> fmt::Debug for Response<'a, T>
72where
73	T: Serialize + Clone,
74{
75	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76		f.write_str(&serde_json::to_string(&self).expect("valid JSON; qed"))
77	}
78}
79
80/// JSON-RPC response object as defined in the [spec](https://www.jsonrpc.org/specification#response_object)
81/// but differs from [`Response`] as it only represent a successful response.
82#[derive(Debug)]
83pub struct Success<'a, T> {
84	/// JSON-RPC version.
85	pub jsonrpc: Option<TwoPointZero>,
86	/// Result.
87	pub result: T,
88	/// Request ID
89	pub id: Id<'a>,
90}
91
92impl<'a, T: Clone> TryFrom<Response<'a, T>> for Success<'a, T> {
93	type Error = ErrorObjectOwned;
94
95	fn try_from(rp: Response<'a, T>) -> Result<Self, Self::Error> {
96		match rp.payload {
97			ResponsePayload::Error(e) => Err(e.into_owned()),
98			ResponsePayload::Success(r) => Ok(Success { jsonrpc: rp.jsonrpc, result: r.into_owned(), id: rp.id }),
99		}
100	}
101}
102
103/// Return value for subscriptions.
104#[derive(Serialize, Deserialize, Debug)]
105pub struct SubscriptionPayload<'a, T> {
106	/// Subscription ID
107	#[serde(borrow)]
108	pub subscription: SubscriptionId<'a>,
109	/// Result.
110	pub result: T,
111}
112
113/// Subscription response object, embedding a [`SubscriptionPayload`] in the `params` member along with `result` field.
114pub type SubscriptionResponse<'a, T> = Notification<'a, SubscriptionPayload<'a, T>>;
115/// Subscription response object, embedding a [`SubscriptionPayload`] in the `params` member along with `error` field.
116pub type SubscriptionError<'a, T> = Notification<'a, SubscriptionPayloadError<'a, T>>;
117
118/// Error value for subscriptions.
119#[derive(Serialize, Deserialize, Debug)]
120pub struct SubscriptionPayloadError<'a, T> {
121	/// Subscription ID
122	#[serde(borrow)]
123	pub subscription: SubscriptionId<'a>,
124	/// Result.
125	pub error: T,
126}
127
128/// Represent the payload of the JSON-RPC response object
129///
130/// It can be:
131///
132/// ```json
133/// "result":<value>
134/// "error":{"code":<code>,"message":<msg>,"data":<data>}
135/// ```
136#[derive(Debug, Clone, PartialEq)]
137pub enum ResponsePayload<'a, T>
138where
139	T: Clone,
140{
141	/// Corresponds to successful JSON-RPC response with the field `result`.
142	Success(StdCow<'a, T>),
143	/// Corresponds to failed JSON-RPC response with a error object with the field `error.
144	Error(ErrorObject<'a>),
145}
146
147impl<'a, T: Clone> ResponsePayload<'a, T> {
148	/// Create a successful owned response payload.
149	pub fn success(t: T) -> Self {
150		Self::Success(StdCow::Owned(t))
151	}
152
153	/// Create a successful borrowed response payload.
154	pub fn success_borrowed(t: &'a T) -> Self {
155		Self::Success(StdCow::Borrowed(t))
156	}
157
158	/// Convert the response payload into owned.
159	pub fn into_owned(self) -> ResponsePayload<'static, T> {
160		match self {
161			Self::Error(e) => ResponsePayload::Error(e.into_owned()),
162			Self::Success(r) => ResponsePayload::Success(StdCow::Owned(r.into_owned())),
163		}
164	}
165
166	/// Create an error response payload.
167	pub fn error(e: impl Into<ErrorObjectOwned>) -> Self {
168		Self::Error(e.into())
169	}
170
171	/// Create a borrowed error response payload.
172	pub fn error_borrowed(e: impl Into<ErrorObject<'a>>) -> Self {
173		Self::Error(e.into())
174	}
175}
176
177impl<'a, T: Clone> From<ErrorCode> for ResponsePayload<'a, T> {
178	fn from(code: ErrorCode) -> ResponsePayload<'a, T> {
179		Self::Error(code.into())
180	}
181}
182
183impl<'de, T> Deserialize<'de> for Response<'de, T>
184where
185	T: Deserialize<'de> + Clone,
186{
187	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
188	where
189		D: Deserializer<'de>,
190		T: Deserialize<'de> + Clone,
191	{
192		#[derive(Debug)]
193		enum Field {
194			Jsonrpc,
195			Result,
196			Error,
197			Id,
198			Ignore,
199		}
200
201		impl<'de> Deserialize<'de> for Field {
202			fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
203			where
204				D: Deserializer<'de>,
205			{
206				struct FieldVisitor;
207
208				impl<'de> serde::de::Visitor<'de> for FieldVisitor {
209					type Value = Field;
210
211					fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
212						formatter.write_str("`jsonrpc`, `result`, `error` and `id`")
213					}
214
215					fn visit_str<E>(self, value: &str) -> Result<Field, E>
216					where
217						E: serde::de::Error,
218					{
219						match value {
220							"jsonrpc" => Ok(Field::Jsonrpc),
221							"result" => Ok(Field::Result),
222							"error" => Ok(Field::Error),
223							"id" => Ok(Field::Id),
224							_ => Ok(Field::Ignore),
225						}
226					}
227				}
228				deserializer.deserialize_identifier(FieldVisitor)
229			}
230		}
231
232		struct Visitor<T>(PhantomData<T>);
233
234		impl<T> Visitor<T> {
235			fn new() -> Visitor<T> {
236				Visitor(PhantomData)
237			}
238		}
239
240		impl<'de, T> serde::de::Visitor<'de> for Visitor<T>
241		where
242			T: Deserialize<'de> + Clone + 'de,
243		{
244			type Value = Response<'de, T>;
245
246			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
247				formatter.write_str("struct Response")
248			}
249
250			fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
251			where
252				V: serde::de::MapAccess<'de>,
253			{
254				let mut jsonrpc = None;
255				let mut result = None;
256				let mut error = None;
257				let mut id = None;
258				while let Some(key) = map.next_key()? {
259					match key {
260						Field::Result => {
261							if result.is_some() {
262								return Err(serde::de::Error::duplicate_field("result"));
263							}
264							result = Some(map.next_value()?);
265						}
266						Field::Error => {
267							if error.is_some() {
268								return Err(serde::de::Error::duplicate_field("error"));
269							}
270							error = Some(map.next_value()?);
271						}
272						Field::Id => {
273							if id.is_some() {
274								return Err(serde::de::Error::duplicate_field("id"));
275							}
276							id = Some(map.next_value()?);
277						}
278						Field::Jsonrpc => {
279							if jsonrpc.is_some() {
280								return Err(serde::de::Error::duplicate_field("jsonrpc"));
281							}
282							jsonrpc = Some(map.next_value()?);
283						}
284						Field::Ignore => {
285							let _ = map.next_value::<serde::de::IgnoredAny>()?;
286						}
287					}
288				}
289
290				let id = id.ok_or_else(|| serde::de::Error::missing_field("id"))?;
291
292				let response = match (jsonrpc, result, error) {
293					(_, Some(_), Some(_)) => {
294						return Err(serde::de::Error::duplicate_field("result and error are mutually exclusive"))
295					}
296					(Some(jsonrpc), Some(result), None) => {
297						Response { jsonrpc, payload: ResponsePayload::Success(result), id }
298					}
299					(Some(jsonrpc), None, Some(err)) => Response { jsonrpc, payload: ResponsePayload::Error(err), id },
300					(None, Some(result), _) => {
301						Response { jsonrpc: None, payload: ResponsePayload::Success(result), id }
302					}
303					(None, _, Some(err)) => Response { jsonrpc: None, payload: ResponsePayload::Error(err), id },
304					(_, None, None) => return Err(serde::de::Error::missing_field("result/error")),
305				};
306
307				Ok(response)
308			}
309		}
310
311		const FIELDS: &[&str] = &["jsonrpc", "result", "error", "id"];
312		deserializer.deserialize_struct("Response", FIELDS, Visitor::new())
313	}
314}
315
316impl<'a, T> Serialize for Response<'a, T>
317where
318	T: Serialize + Clone,
319{
320	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
321	where
322		S: Serializer,
323	{
324		let mut s = serializer.serialize_struct("Response", 3)?;
325
326		if let Some(field) = &self.jsonrpc {
327			s.serialize_field("jsonrpc", field)?;
328		}
329
330		s.serialize_field("id", &self.id)?;
331
332		match &self.payload {
333			ResponsePayload::Error(err) => s.serialize_field("error", err)?,
334			ResponsePayload::Success(r) => s.serialize_field("result", r)?,
335		};
336
337		s.end()
338	}
339}
340
341#[cfg(test)]
342mod tests {
343	use super::{Id, Response, TwoPointZero};
344	use crate::{response::ResponsePayload, ErrorObjectOwned};
345
346	#[test]
347	fn serialize_call_ok_response() {
348		let ser = serde_json::to_string(&Response {
349			jsonrpc: Some(TwoPointZero),
350			payload: ResponsePayload::success("ok"),
351			id: Id::Number(1),
352		})
353		.unwrap();
354		let exp = r#"{"jsonrpc":"2.0","id":1,"result":"ok"}"#;
355		assert_eq!(ser, exp);
356	}
357
358	#[test]
359	fn serialize_call_err_response() {
360		let ser = serde_json::to_string(&Response {
361			jsonrpc: Some(TwoPointZero),
362			payload: ResponsePayload::<()>::error(ErrorObjectOwned::owned(1, "lo", None::<()>)),
363			id: Id::Number(1),
364		})
365		.unwrap();
366		let exp = r#"{"jsonrpc":"2.0","id":1,"error":{"code":1,"message":"lo"}}"#;
367		assert_eq!(ser, exp);
368	}
369
370	#[test]
371	fn serialize_call_response_missing_version_field() {
372		let ser = serde_json::to_string(&Response {
373			jsonrpc: None,
374			payload: ResponsePayload::success("ok"),
375			id: Id::Number(1),
376		})
377		.unwrap();
378		let exp = r#"{"id":1,"result":"ok"}"#;
379		assert_eq!(ser, exp);
380	}
381
382	#[test]
383	fn deserialize_success_call() {
384		let exp =
385			Response { jsonrpc: Some(TwoPointZero), payload: ResponsePayload::success(99_u64), id: Id::Number(11) };
386		let dsr: Response<u64> = serde_json::from_str(r#"{"jsonrpc":"2.0", "result":99, "id":11}"#).unwrap();
387		assert_eq!(dsr.jsonrpc, exp.jsonrpc);
388		assert_eq!(dsr.payload, exp.payload);
389		assert_eq!(dsr.id, exp.id);
390	}
391
392	#[test]
393	fn deserialize_err_call() {
394		let exp = Response {
395			jsonrpc: Some(TwoPointZero),
396			payload: ResponsePayload::error(ErrorObjectOwned::owned(1, "lo", None::<()>)),
397			id: Id::Number(11),
398		};
399		let dsr: Response<()> =
400			serde_json::from_str(r#"{"jsonrpc":"2.0","error":{"code":1,"message":"lo"},"id":11}"#).unwrap();
401		assert_eq!(dsr.jsonrpc, exp.jsonrpc);
402		assert_eq!(dsr.payload, exp.payload);
403		assert_eq!(dsr.id, exp.id);
404	}
405
406	#[test]
407	fn deserialize_call_missing_version_field() {
408		let exp = Response { jsonrpc: None, payload: ResponsePayload::success(99_u64), id: Id::Number(11) };
409		let dsr: Response<u64> = serde_json::from_str(r#"{"jsonrpc":null, "result":99, "id":11}"#).unwrap();
410		assert_eq!(dsr.jsonrpc, exp.jsonrpc);
411		assert_eq!(dsr.payload, exp.payload);
412		assert_eq!(dsr.id, exp.id);
413	}
414
415	#[test]
416	fn deserialize_with_unknown_field() {
417		let exp = Response { jsonrpc: None, payload: ResponsePayload::success(99_u64), id: Id::Number(11) };
418		let dsr: Response<u64> =
419			serde_json::from_str(r#"{"jsonrpc":null, "result":99, "id":11, "unknown":11}"#).unwrap();
420		assert_eq!(dsr.jsonrpc, exp.jsonrpc);
421		assert_eq!(dsr.payload, exp.payload);
422		assert_eq!(dsr.id, exp.id);
423	}
424}