use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer, Error as SerError};
use serde_json::value::from_value;
use super::{Id, Params, Version, Value};
#[derive(Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct MethodCall {
pub jsonrpc: Version,
pub method: String,
pub params: Option<Params>,
pub id: Id,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Notification {
pub jsonrpc: Version,
pub method: String,
pub params: Option<Params>
}
#[derive(Debug, PartialEq)]
pub enum Call {
MethodCall(MethodCall),
Notification(Notification),
Invalid
}
impl Serialize for Call {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer {
match *self {
Call::MethodCall(ref m) => m.serialize(serializer),
Call::Notification(ref n) => n.serialize(serializer),
Call::Invalid => Err(S::Error::custom("invalid call"))
}
}
}
impl Deserialize for Call {
fn deserialize<D>(deserializer: &mut D) -> Result<Call, D::Error>
where D: Deserializer {
let v = try!(Value::deserialize(deserializer));
from_value(v.clone()).map(Call::Notification)
.or_else(|_| from_value(v).map(Call::MethodCall))
.map_err(|_| D::Error::custom("")) .or_else(|_: D::Error | Ok(Call::Invalid))
}
}
#[derive(Debug, PartialEq)]
pub enum Request {
Single(Call),
Batch(Vec<Call>)
}
impl Serialize for Request {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer {
match *self {
Request::Single(ref call) => call.serialize(serializer),
Request::Batch(ref calls) => calls.serialize(serializer),
}
}
}
impl Deserialize for Request {
fn deserialize<D>(deserializer: &mut D) -> Result<Request, D::Error>
where D: Deserializer {
let v = try!(Value::deserialize(deserializer));
from_value(v.clone()).map(Request::Batch)
.or_else(|_| from_value(v).map(Request::Single))
.map_err(|_| D::Error::custom("")) }
}
#[test]
fn method_call_serialize() {
use serde_json;
use serde_json::Value;
let m = MethodCall {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1), Value::U64(2)])),
id: Id::Num(1)
};
let serialized = serde_json::to_string(&m).unwrap();
assert_eq!(serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2],"id":1}"#);
}
#[test]
fn notification_serialize() {
use serde_json;
use serde_json::Value;
let n = Notification {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1), Value::U64(2)]))
};
let serialized = serde_json::to_string(&n).unwrap();
assert_eq!(serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2]}"#);
}
#[test]
fn call_serialize() {
use serde_json;
use serde_json::Value;
let n = Call::Notification(Notification {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1)]))
});
let serialized = serde_json::to_string(&n).unwrap();
assert_eq!(serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1]}"#);
}
#[test]
fn request_serialize_batch() {
use serde_json;
let batch = Request::Batch(vec![
Call::MethodCall(MethodCall {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1), Value::U64(2)])),
id: Id::Num(1)
}),
Call::Notification(Notification {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1)]))
})
]);
let serialized = serde_json::to_string(&batch).unwrap();
assert_eq!(serialized, r#"[{"jsonrpc":"2.0","method":"update","params":[1,2],"id":1},{"jsonrpc":"2.0","method":"update","params":[1]}]"#);
}
#[test]
fn notification_deserialize() {
use serde_json;
use serde_json::Value;
let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1,2]}"#;
let deserialized: Notification = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Notification {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1), Value::U64(2)]))
});
let s = r#"{"jsonrpc": "2.0", "method": "foobar"}"#;
let deserialized: Notification = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Notification {
jsonrpc: Version::V2,
method: "foobar".to_owned(),
params: None
});
let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1,2], "id": 1}"#;
let deserialized: Result<Notification, _> = serde_json::from_str(s);
assert!(deserialized.is_err())
}
#[test]
fn call_deserialize() {
use serde_json;
let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1]}"#;
let deserialized: Call = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Call::Notification(Notification {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1)]))
}));
let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1], "id": 1}"#;
let deserialized: Call = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Call::MethodCall(MethodCall {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1)])),
id: Id::Num(1)
}));
}
#[test]
fn request_deserialize_batch() {
use serde_json;
let s = r#"[1, {"jsonrpc": "2.0", "method": "update", "params": [1,2], "id": 1},{"jsonrpc": "2.0", "method": "update", "params": [1]}]"#;
let deserialized: Request = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Request::Batch(vec![
Call::Invalid,
Call::MethodCall(MethodCall {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1), Value::U64(2)])),
id: Id::Num(1)
}),
Call::Notification(Notification {
jsonrpc: Version::V2,
method: "update".to_owned(),
params: Some(Params::Array(vec![Value::U64(1)]))
})
]))
}