jsonrpc/
jsonrpc_response.rs

1// Copyright 2016 Bruno Medeiros
2//
3// Licensed under the Apache License, Version 2.0 
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>. 
5// This file may not be copied, modified, or distributed
6// except according to those terms.
7
8
9use serde;
10use serde_json;
11use serde_json::Value;
12
13use jsonrpc_common::*;
14use jsonrpc_request::check_jsonrpc_field;
15use json_util::*;
16
17
18/* ----------------- Response ----------------- */
19
20/// A JSON RPC response, version 2.0.
21/// Only one of 'result' or 'error' is defined.
22#[derive(Debug, PartialEq, Clone)]
23pub struct Response {
24    // Rpc id. Note: spec requires key `id` to be present
25    pub id : Id, 
26    // field `result` or field `error`:
27    pub result_or_error: ResponseResult,
28}
29
30impl Response {
31    pub fn new_result(id: Id, result: Value) -> Response {
32        Response { id : id, result_or_error : ResponseResult::Result(result) }
33    }
34    
35    pub fn new_error(id: Id, error: RequestError) -> Response {
36        Response { id : id, result_or_error : ResponseResult::Error(error) }
37    }
38}
39
40
41/// The result-or-error part of JSON RPC response.
42#[derive(Debug, PartialEq, Clone)]
43pub enum ResponseResult {
44    Result(Value),
45    Error(RequestError)
46}
47
48impl ResponseResult {
49    pub fn unwrap_result(self) -> Value {
50        match self {
51        	ResponseResult::Result(value) => value,
52        	_ => panic!("Expected a ResponseResult::Result")
53        }
54    }
55    
56    pub fn new_error(id: Id, error: RequestError) -> Response {
57        Response { id : id, result_or_error : ResponseResult::Error(error) }
58    }
59}
60
61
62impl serde::Serialize for Response {
63    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
64        where S: serde::Serializer
65    {
66        let elem_count = 3;
67        let mut state = try!(serializer.serialize_struct("Response", elem_count));
68        {
69            try!(serializer.serialize_struct_elt(&mut state, "jsonrpc", "2.0"));
70            try!(serializer.serialize_struct_elt(&mut state, "id", &self.id));
71            
72            match self.result_or_error {
73                ResponseResult::Result(ref value) => {
74                    try!(serializer.serialize_struct_elt(&mut state, "result", &value));
75                }
76                ResponseResult::Error(ref json_rpc_error) => {
77                    try!(serializer.serialize_struct_elt(&mut state, "error", &json_rpc_error)); 
78                }
79            }
80        }
81        serializer.serialize_struct_end(state)
82    }
83}
84
85impl serde::Deserialize for Response {
86    fn deserialize<DE>(deserializer: &mut DE) -> Result<Self, DE::Error>
87        where DE: serde::Deserializer 
88    {
89        let mut helper = SerdeJsonDeserializerHelper(deserializer);
90        let value = try!(Value::deserialize(helper.0));
91        let mut json_obj = try!(helper.as_Object(value));
92        
93        try!(check_jsonrpc_field(&mut helper, &mut json_obj));
94        
95        let id_value = try!(helper.obtain_Value(&mut json_obj, "id"));
96        let id : Id = try!(serde_json::from_value(id_value).map_err(to_de_error));
97        
98        let result_or_error : ResponseResult = {
99            if let Some(result) = json_obj.remove("result") {
100                ResponseResult::Result(result)
101            } else  
102            if let Some(error_obj) = json_obj.remove("error") {
103                let error : RequestError = try!(serde_json::from_value(error_obj).map_err(to_de_error));
104                ResponseResult::Error(error)
105            } else {
106                return Err(new_de_error("Missing property `result` or `error`".to_string()));
107            }
108        };
109        
110        Ok(Response{ id : id, result_or_error : result_or_error }) 
111    }
112}
113
114#[cfg(test)]
115pub mod response_tests {
116
117    use super::*;
118    use jsonrpc_common::*;
119    
120    use json_util::*;
121    use json_util::test_util::*;
122    
123    use serde_json::Value;
124    use serde_json::builder::ObjectBuilder;
125
126    pub fn sample_json_obj(foo: u32) -> Value {
127        ObjectBuilder::new().insert("foo", foo).build()
128    }
129    
130    #[test]
131    fn test_Response() {
132        
133        test_error_de::<Response>(
134            r#"{ "id":123, "result":null }"#, 
135            "Property `jsonrpc` is missing.",
136        );
137        test_error_de::<Response>(
138            r#"{ "jsonrpc":"1", "id":123, "result":null }"#, 
139            r#"Property `jsonrpc` is not "2.0". "#
140        );
141        
142        test_error_de::<Response>(
143            r#"{ "jsonrpc":"2.0" }"#, 
144            "Property `id` is missing"
145        );
146        test_error_de::<Response>(
147            r#"{ "jsonrpc":"2.0", "id":123 }"#, 
148            "Missing property `result` or `error`"
149        );
150
151        
152        let response = Response::new_result(Id::Null, sample_json_obj(100));
153        test_serde_expecting(&response, &ObjectBuilder::new()
154            .insert("jsonrpc", "2.0")
155            .insert("id", Id::Null)
156            .insert("result", sample_json_obj(100))
157            .build()
158        ); 
159        
160        let response = Response::new_result(Id::Number(123), sample_json_obj(200));
161        test_serde_expecting(&response, &ObjectBuilder::new()
162            .insert("jsonrpc", "2.0")
163            .insert("id", 123)
164            .insert("result", sample_json_obj(200))
165            .build()
166        );
167        
168        let response = Response::new_result(Id::Null, sample_json_obj(200));
169        test_serde_expecting(&response, &ObjectBuilder::new()
170            .insert("jsonrpc", "2.0")
171            .insert("id", Value::Null)
172            .insert("result", sample_json_obj(200))
173            .build()
174        );
175        
176        let response = Response::new_error(Id::String("321".to_string()), RequestError{
177            code: 5, message: "msg".to_string(), data: Some(sample_json_obj(300))
178        });
179        test_serde_expecting(&response, &ObjectBuilder::new()
180            .insert("jsonrpc", "2.0")
181            .insert("id", "321")
182            .insert("error", unwrap_object_builder(ObjectBuilder::new()
183                .insert("code", 5)
184                .insert("message", "msg")
185                .insert("data", sample_json_obj(300))
186            ))
187            .build()
188        );
189        
190    }
191}