jsonrpc/
jsonrpc_request.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::de::Visitor;
11use serde::de;
12use serde::Error;
13
14use serde_json;
15use serde_json::Value;
16
17use util::core::GResult;
18
19use jsonrpc_common::*;
20use json_util::*;
21
22/* -----------------  ----------------- */
23
24pub fn check_jsonrpc_field<ERR, HELPER>(helper: &mut HELPER, json_obj: &mut JsonObject) -> Result<(), ERR>
25where 
26    HELPER: JsonDeserializerHelper<ERR>, 
27{
28    let jsonrpc = try!(helper.obtain_String(json_obj, "jsonrpc"));
29    if jsonrpc != "2.0" {
30        return Err(helper.new_error(r#"Property `jsonrpc` is not "2.0". "#))
31    };
32    Ok(())
33}
34
35/* -----------------  Request  ----------------- */
36
37/// A JSON RPC request, version 2.0
38#[derive(Debug, PartialEq, Clone)]
39pub struct Request {
40    // ommited jsonrpc field, must be "2.0" when serialized
41    //pub jsonrpc : String, 
42    pub id : Option<Id>,
43    pub method : String,
44    pub params : RequestParams,
45}
46
47impl Request {
48    pub fn new(id_number: u64, method: String, params: JsonObject) -> Request {
49        Request {
50            id : Some(Id::Number(id_number)),
51            method : method,
52            params : RequestParams::Object(params),
53        } 
54    }
55}
56
57impl serde::Serialize for Request {
58    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
59        where S: serde::Serializer
60    {
61        // TODO: need to investigate if elem_count = 4 is actually valid when id is missing
62        // serializing to JSON seems to not be a problem, but there might be other issues
63        let elem_count = 4;
64        let mut state = try!(serializer.serialize_struct("Request", elem_count)); 
65        {
66            try!(serializer.serialize_struct_elt(&mut state, "jsonrpc", "2.0"));
67            if let Some(ref id) = self.id {
68                try!(serializer.serialize_struct_elt(&mut state, "id", id));
69            }
70            try!(serializer.serialize_struct_elt(&mut state, "method", &self.method));
71            try!(serializer.serialize_struct_elt(&mut state, "params", &self.params));
72        }
73        serializer.serialize_struct_end(state)
74    }
75}
76
77impl serde::Deserialize for Request {
78    fn deserialize<DE>(deserializer: &mut DE) -> Result<Self, DE::Error>
79        where DE: serde::Deserializer 
80    {
81        let mut helper = SerdeJsonDeserializerHelper(deserializer);
82        let value = try!(Value::deserialize(helper.0));
83        let mut json_obj = try!(helper.as_Object(value));
84        
85        try!(check_jsonrpc_field(&mut helper, &mut json_obj));
86        
87        let id = json_obj.remove("id");
88        let id = try!(id.map_or(Ok(None), |value| serde_json::from_value(value).map_err(to_de_error)));
89        let method = try!(helper.obtain_String(&mut json_obj, "method"));
90        let params = try!(helper.obtain_Value(&mut json_obj, "params"));
91        
92        let params = try!(to_jsonrpc_params(params).map_err(to_de_error));
93        
94        Ok(Request { id : id, method : method, params : params })
95    }
96}
97
98
99/* -----------------  ----------------- */
100
101#[derive(Debug, PartialEq, Clone)]
102pub enum RequestParams {
103    Object(JsonObject),
104    Array(Vec<Value>),
105    None,
106}
107
108impl RequestParams {
109    pub fn into_value(self) -> Value {
110        // Note, we could use serde_json::to_value(&params) but that is less efficient:
111        // it reserializes the value, instead of just obtaining the underlying one 
112        
113        match self {
114            RequestParams::Object(object) => Value::Object(object),
115            RequestParams::Array(array) => Value::Array(array),
116            RequestParams::None => Value::Null,
117        }
118    }
119}
120
121impl serde::Serialize for RequestParams {
122    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
123        where S: serde::Serializer
124    {
125        match *self {
126            RequestParams::Object(ref object) => object.serialize(serializer),
127            RequestParams::Array(ref array) => array.serialize(serializer),
128            RequestParams::None => serializer.serialize_none(),
129        }
130    }
131}
132
133pub fn to_jsonrpc_params(params: Value) -> GResult<RequestParams> {
134    match params {
135        Value::Object(object) => Ok(RequestParams::Object(object)),
136        Value::Array(array) => Ok(RequestParams::Array(array)),
137        Value::Null => Ok(RequestParams::None),
138        _ => Err("Property `params` not an Object, Array, or null.".into()),
139    }
140}
141
142impl serde::Deserialize for RequestParams {
143    fn deserialize<DE>(deserializer: &mut DE) -> Result<Self, DE::Error>
144        where DE: serde::Deserializer 
145    {
146        deserializer.deserialize(RequestParams_DeserializeVisitor)
147    }
148}
149
150struct RequestParams_DeserializeVisitor;
151
152impl Visitor for RequestParams_DeserializeVisitor {
153    type Value = RequestParams;
154    
155    fn visit_unit<E>(&mut self) -> Result<Self::Value, E> 
156        where E: Error,
157    {
158        Ok(RequestParams::None)
159    }
160    
161    fn visit_seq<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
162        where V: de::SeqVisitor,
163    {
164        let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
165        Ok(RequestParams::Array(values))
166    }
167
168    fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
169        where V: de::MapVisitor,
170    {
171        let values = try!(de::impls::BTreeMapVisitor::new().visit_map(visitor));
172        Ok(RequestParams::Object(values))
173    }
174    
175}
176
177
178
179#[cfg(test)]
180pub mod request_tests {
181
182    use super::*;
183    
184    use util::tests::*;
185    use json_util::*;
186    use json_util::test_util::*;
187    use jsonrpc_common::*;
188    
189    use serde_json::Value;
190    use serde_json::builder::ObjectBuilder;
191
192
193    #[test]
194    fn test__RequestParams() {
195        
196        let sample_obj = unwrap_object_builder(ObjectBuilder::new().insert("xxx", 123));
197        let sample_string = Value::String("blah".into());
198        
199        test_serde__RequestParams(RequestParams::Object(sample_obj.clone()));
200        test_serde__RequestParams(RequestParams::Array(vec![sample_string.clone(), sample_string]));
201        test_serde__RequestParams(RequestParams::None);
202    }
203    
204    fn test_serde__RequestParams(params: RequestParams) {
205        let params_reser = test_serde(&params).0;
206        assert_equal(params_reser, params);
207    }
208    
209    pub fn check_error(result: RequestError, expected: RequestError) {
210        assert_starts_with(&result.message, &expected.message);
211        assert_eq!(result, RequestError { message : result.message.clone(), .. expected }); 
212    }
213    
214    #[test]
215    fn test_Request() {
216        
217        let sample_params = unwrap_object_builder(ObjectBuilder::new()
218            .insert("param", "2.0")
219            .insert("foo", 123)
220        );
221        
222        // Test invalid JSON
223        test_error_de::<Request>(
224            "{",
225            "EOF while"
226        );
227        
228        test_error_de::<Request>(
229            "{ }",
230            "Property `jsonrpc` is missing.",
231        );
232        
233        test_error_de::<Request>(
234            r#"{ "jsonrpc": "1.0" }"#,
235            r#"Property `jsonrpc` is not "2.0". "#,
236        );
237        
238        test_error_de::<Request>(
239            r#"{ "jsonrpc": "2.0" }"#,
240            "Property `method` is missing.",
241        );
242        test_error_de::<Request>(
243            r#"{ "jsonrpc": "2.0", "method":null }"#,
244            "Value `null` is not a String.",
245        );
246        
247        test_error_de::<Request>(
248            r#"{ "jsonrpc": "2.0", "method":"xxx" }"#,
249            "Property `params` is missing.",
250        );
251        
252        // Test valid request with params = null
253        assert_equal(
254            from_json(r#"{ "jsonrpc": "2.0", "method":"xxx", "params":null }"#),
255            Request { id : None, method : "xxx".into(), params : RequestParams::None, } 
256        );
257        
258        // --- Test serialization ---
259        
260        // basic Request
261        let request = Request::new(1, "myMethod".to_string(), sample_params.clone());
262        test_serde(&request);
263        
264        // Test basic Request, no params
265        let request = Request { id : None, method : "myMethod".to_string(), params : RequestParams::None, };
266        test_serde(&request);
267        
268        // Test Request with no id
269        let sample_array_params = RequestParams::Array(vec![]);
270        let request = Request { id : None, method : "myMethod".to_string(), params : sample_array_params, };  
271        test_serde(&request);
272    }
273    
274}