blob: 5514f8b7a58642c84c0984b1d03fa36e80de3de2 [file] [log] [blame]
//! jsonrpc request
use super::{Id, Params, Version};
/// Represents jsonrpc request which is a method call.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct MethodCall {
/// A String specifying the version of the JSON-RPC protocol.
pub jsonrpc: Option<Version>,
/// A String containing the name of the method to be invoked.
pub method: String,
/// A Structured value that holds the parameter values to be used
/// during the invocation of the method. This member MAY be omitted.
#[serde(default = "default_params")]
pub params: Params,
/// An identifier established by the Client that MUST contain a String,
/// Number, or NULL value if included. If it is not included it is assumed
/// to be a notification.
pub id: Id,
}
/// Represents jsonrpc request which is a notification.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Notification {
/// A String specifying the version of the JSON-RPC protocol.
pub jsonrpc: Option<Version>,
/// A String containing the name of the method to be invoked.
pub method: String,
/// A Structured value that holds the parameter values to be used
/// during the invocation of the method. This member MAY be omitted.
#[serde(default = "default_params")]
pub params: Params,
}
/// Represents single jsonrpc call.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Call {
/// Call method
MethodCall(MethodCall),
/// Fire notification
Notification(Notification),
/// Invalid call
Invalid {
/// Call id (if known)
#[serde(default = "default_id")]
id: Id,
},
}
fn default_params() -> Params {
Params::None
}
fn default_id() -> Id {
Id::Null
}
impl From<MethodCall> for Call {
fn from(mc: MethodCall) -> Self {
Call::MethodCall(mc)
}
}
impl From<Notification> for Call {
fn from(n: Notification) -> Self {
Call::Notification(n)
}
}
/// Represents jsonrpc request.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Request {
/// Single request (call)
Single(Call),
/// Batch of requests (calls)
Batch(Vec<Call>),
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::Value;
#[test]
fn method_call_serialize() {
use serde_json;
use serde_json::Value;
let m = MethodCall {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1), Value::from(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: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1), Value::from(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: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(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: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1), Value::from(2)]),
id: Id::Num(1),
}),
Call::Notification(Notification {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(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: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1), Value::from(2)])
}
);
let s = r#"{"jsonrpc": "2.0", "method": "foobar"}"#;
let deserialized: Notification = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Notification {
jsonrpc: Some(Version::V2),
method: "foobar".to_owned(),
params: 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: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(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: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1)]),
id: Id::Num(1)
})
);
let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [], "id": 1}"#;
let deserialized: Call = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Call::MethodCall(MethodCall {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![]),
id: Id::Num(1)
})
);
let s = r#"{"jsonrpc": "2.0", "method": "update", "params": null, "id": 1}"#;
let deserialized: Call = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Call::MethodCall(MethodCall {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::None,
id: Id::Num(1)
})
);
let s = r#"{"jsonrpc": "2.0", "method": "update", "id": 1}"#;
let deserialized: Call = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Call::MethodCall(MethodCall {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::None,
id: Id::Num(1)
})
);
}
#[test]
fn request_deserialize_batch() {
use serde_json;
let s = r#"[{}, {"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 { id: Id::Null },
Call::MethodCall(MethodCall {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1), Value::from(2)]),
id: Id::Num(1)
}),
Call::Notification(Notification {
jsonrpc: Some(Version::V2),
method: "update".to_owned(),
params: Params::Array(vec![Value::from(1)])
})
])
)
}
#[test]
fn request_invalid_returns_id() {
use serde_json;
let s = r#"{"id":120,"method":"my_method","params":["foo", "bar"],"extra_field":[]}"#;
let deserialized: Request = serde_json::from_str(s).unwrap();
match deserialized {
Request::Single(Call::Invalid { id: Id::Num(120) }) => {}
_ => panic!("Request wrongly deserialized: {:?}", deserialized),
}
}
}