jsonrpc_core/types/
response.rs

1//! jsonrpc response
2use super::{Error, ErrorCode, Id, Value, Version};
3use crate::Result as CoreResult;
4
5/// Successful response
6#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
7#[serde(deny_unknown_fields)]
8pub struct Success {
9	/// Protocol version
10	#[serde(skip_serializing_if = "Option::is_none")]
11	pub jsonrpc: Option<Version>,
12	/// Result
13	pub result: Value,
14	/// Correlation id
15	pub id: Id,
16}
17
18/// Unsuccessful response
19#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct Failure {
22	/// Protocol Version
23	#[serde(skip_serializing_if = "Option::is_none")]
24	pub jsonrpc: Option<Version>,
25	/// Error
26	pub error: Error,
27	/// Correlation id
28	pub id: Id,
29}
30
31/// Represents output - failure or success
32#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
33#[serde(deny_unknown_fields)]
34#[serde(untagged)]
35pub enum Output {
36	/// Success
37	Success(Success),
38	/// Failure
39	Failure(Failure),
40}
41
42impl Output {
43	/// Creates new output given `Result`, `Id` and `Version`.
44	pub fn from(result: CoreResult<Value>, id: Id, jsonrpc: Option<Version>) -> Self {
45		match result {
46			Ok(result) => Output::Success(Success { jsonrpc, result, id }),
47			Err(error) => Output::Failure(Failure { jsonrpc, error, id }),
48		}
49	}
50
51	/// Creates new failure output indicating malformed request.
52	pub fn invalid_request(id: Id, jsonrpc: Option<Version>) -> Self {
53		Output::Failure(Failure {
54			id,
55			jsonrpc,
56			error: Error::new(ErrorCode::InvalidRequest),
57		})
58	}
59
60	/// Get the jsonrpc protocol version.
61	pub fn version(&self) -> Option<Version> {
62		match *self {
63			Output::Success(ref s) => s.jsonrpc,
64			Output::Failure(ref f) => f.jsonrpc,
65		}
66	}
67
68	/// Get the correlation id.
69	pub fn id(&self) -> &Id {
70		match *self {
71			Output::Success(ref s) => &s.id,
72			Output::Failure(ref f) => &f.id,
73		}
74	}
75}
76
77impl From<Output> for CoreResult<Value> {
78	/// Convert into a result. Will be `Ok` if it is a `Success` and `Err` if `Failure`.
79	fn from(output: Output) -> CoreResult<Value> {
80		match output {
81			Output::Success(s) => Ok(s.result),
82			Output::Failure(f) => Err(f.error),
83		}
84	}
85}
86
87/// Synchronous response
88#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
89#[serde(deny_unknown_fields)]
90#[serde(untagged)]
91pub enum Response {
92	/// Single response
93	Single(Output),
94	/// Response to batch request (batch of responses)
95	Batch(Vec<Output>),
96}
97
98impl Response {
99	/// Creates new `Response` with given error and `Version`
100	pub fn from(error: Error, jsonrpc: Option<Version>) -> Self {
101		Failure {
102			id: Id::Null,
103			jsonrpc,
104			error,
105		}
106		.into()
107	}
108
109	/// Deserialize `Response` from given JSON string.
110	///
111	/// This method will handle an empty string as empty batch response.
112	pub fn from_json(s: &str) -> Result<Self, serde_json::Error> {
113		if s.is_empty() {
114			Ok(Response::Batch(vec![]))
115		} else {
116			crate::serde_from_str(s)
117		}
118	}
119}
120
121impl From<Failure> for Response {
122	fn from(failure: Failure) -> Self {
123		Response::Single(Output::Failure(failure))
124	}
125}
126
127impl From<Success> for Response {
128	fn from(success: Success) -> Self {
129		Response::Single(Output::Success(success))
130	}
131}
132
133#[test]
134fn success_output_serialize() {
135	use serde_json;
136	use serde_json::Value;
137
138	let so = Output::Success(Success {
139		jsonrpc: Some(Version::V2),
140		result: Value::from(1),
141		id: Id::Num(1),
142	});
143
144	let serialized = serde_json::to_string(&so).unwrap();
145	assert_eq!(serialized, r#"{"jsonrpc":"2.0","result":1,"id":1}"#);
146}
147
148#[test]
149fn success_output_deserialize() {
150	use serde_json;
151	use serde_json::Value;
152
153	let dso = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;
154
155	let deserialized: Output = serde_json::from_str(dso).unwrap();
156	assert_eq!(
157		deserialized,
158		Output::Success(Success {
159			jsonrpc: Some(Version::V2),
160			result: Value::from(1),
161			id: Id::Num(1)
162		})
163	);
164}
165
166#[test]
167fn failure_output_serialize() {
168	use serde_json;
169
170	let fo = Output::Failure(Failure {
171		jsonrpc: Some(Version::V2),
172		error: Error::parse_error(),
173		id: Id::Num(1),
174	});
175
176	let serialized = serde_json::to_string(&fo).unwrap();
177	assert_eq!(
178		serialized,
179		r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#
180	);
181}
182
183#[test]
184fn failure_output_serialize_jsonrpc_1() {
185	use serde_json;
186
187	let fo = Output::Failure(Failure {
188		jsonrpc: None,
189		error: Error::parse_error(),
190		id: Id::Num(1),
191	});
192
193	let serialized = serde_json::to_string(&fo).unwrap();
194	assert_eq!(
195		serialized,
196		r#"{"error":{"code":-32700,"message":"Parse error"},"id":1}"#
197	);
198}
199
200#[test]
201fn failure_output_deserialize() {
202	use serde_json;
203
204	let dfo = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#;
205
206	let deserialized: Output = serde_json::from_str(dfo).unwrap();
207	assert_eq!(
208		deserialized,
209		Output::Failure(Failure {
210			jsonrpc: Some(Version::V2),
211			error: Error::parse_error(),
212			id: Id::Num(1)
213		})
214	);
215}
216
217#[test]
218fn single_response_deserialize() {
219	use serde_json;
220	use serde_json::Value;
221
222	let dsr = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;
223
224	let deserialized: Response = serde_json::from_str(dsr).unwrap();
225	assert_eq!(
226		deserialized,
227		Response::Single(Output::Success(Success {
228			jsonrpc: Some(Version::V2),
229			result: Value::from(1),
230			id: Id::Num(1)
231		}))
232	);
233}
234
235#[test]
236fn batch_response_deserialize() {
237	use serde_json;
238	use serde_json::Value;
239
240	let dbr = r#"[{"jsonrpc":"2.0","result":1,"id":1},{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}]"#;
241
242	let deserialized: Response = serde_json::from_str(dbr).unwrap();
243	assert_eq!(
244		deserialized,
245		Response::Batch(vec![
246			Output::Success(Success {
247				jsonrpc: Some(Version::V2),
248				result: Value::from(1),
249				id: Id::Num(1)
250			}),
251			Output::Failure(Failure {
252				jsonrpc: Some(Version::V2),
253				error: Error::parse_error(),
254				id: Id::Num(1)
255			})
256		])
257	);
258}
259
260#[test]
261fn handle_incorrect_responses() {
262	use serde_json;
263
264	let dsr = r#"
265{
266	"id": 2,
267	"jsonrpc": "2.0",
268	"result": "0x62d3776be72cc7fa62cad6fe8ed873d9bc7ca2ee576e400d987419a3f21079d5",
269	"error": {
270		"message": "VM Exception while processing transaction: revert",
271		"code": -32000,
272		"data": {}
273	}
274}"#;
275
276	let deserialized: Result<Response, _> = serde_json::from_str(dsr);
277	assert!(
278		deserialized.is_err(),
279		"Expected error when deserializing invalid payload."
280	);
281}
282
283#[test]
284fn should_parse_empty_response_as_batch() {
285	use serde_json;
286
287	let dsr = r#""#;
288
289	let deserialized1: Result<Response, _> = serde_json::from_str(dsr);
290	let deserialized2: Result<Response, _> = Response::from_json(dsr);
291	assert!(
292		deserialized1.is_err(),
293		"Empty string is not valid JSON, so we should get an error."
294	);
295	assert_eq!(deserialized2.unwrap(), Response::Batch(vec![]));
296}