1use super::{Error, ErrorCode, Id, Value, Version};
3use crate::Result as CoreResult;
4
5#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
7#[serde(deny_unknown_fields)]
8pub struct Success {
9 #[serde(skip_serializing_if = "Option::is_none")]
11 pub jsonrpc: Option<Version>,
12 pub result: Value,
14 pub id: Id,
16}
17
18#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct Failure {
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub jsonrpc: Option<Version>,
25 pub error: Error,
27 pub id: Id,
29}
30
31#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
33#[serde(deny_unknown_fields)]
34#[serde(untagged)]
35pub enum Output {
36 Success(Success),
38 Failure(Failure),
40}
41
42impl Output {
43 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 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 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 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 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#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
89#[serde(deny_unknown_fields)]
90#[serde(untagged)]
91pub enum Response {
92 Single(Output),
94 Batch(Vec<Output>),
96}
97
98impl Response {
99 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 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}