futures-jsonrpc
Futures + JSON-RPC
A lightweight remote procedure call protocol. It is designed to be simple! And, with futures, even more flexible!
This crate will associate Futures with method signatures via register_method, and parse/handle JSON-RPC messages via handle_message.
It is fully compliant with JSON-RPC 2.0 Specification.
Contributing
The crate is not test covered yet! Any PR with a test coverage will be much appreciated :)
Installation
Add this to your Cargo.toml
:
[dependencies]
futures_jsonrpc = "0.1"
Examples
use futures_jsonrpc::futures::prelude::*;
use futures_jsonrpc::*;
use serde_json::Number;
#[derive(Debug, Clone)]
struct SomeNotification {
request: Option<JrpcRequest>,
}
impl SomeNotification {
pub fn new() -> Result<Self, ErrorVariant> {
let request = None;
let some_notification = SomeNotification { request };
Ok(some_notification)
}
pub fn get_request(&self) -> Result<JrpcRequest, ErrorVariant> {
let request = self.request.clone();
request
.map(|r| Ok(r.clone()))
.unwrap_or(Err(ErrorVariant::NoRequestProvided))
}
pub fn set_request(mut self, request: JrpcRequest) -> Result<Self, ErrorVariant> {
self.request = Some(request);
Ok(self)
}
pub fn clone_with_request(&self, request: JrpcRequest) -> Result<Self, ErrorVariant> {
self.clone().set_request(request)
}
}
impl Future for SomeNotification {
type Item = Option<JrpcResponse>;
type Error = ErrorVariant;
fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
let request = self.get_request()?;
let params = request.get_params().clone().unwrap_or(JsonValue::Null);
let message = JrpcResponseParam::generate_result(params)
.and_then(|result| request.generate_response(result))?;
Ok(Async::Ready(Some(message)))
}
}
impl JrpcMethodTrait for SomeNotification {
fn generate_future<'a>(
&self,
request: JrpcRequest,
) -> Result<Box<'a + Future<Item = Option<JrpcResponse>, Error = ErrorVariant>>, ErrorVariant>
{
Ok(Box::new(self.clone_with_request(request)?))
}
}
generate_method_with_future!(InitializeRequest, impl Future for InitializeRequest {
type Item = Option<JrpcResponse>;
type Error = ErrorVariant;
fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
let request = self.get_request()?;
let params = request.get_params().clone().unwrap_or(JsonValue::Null);
let message = JrpcResponseParam::generate_result(params)
.and_then(|result| request.generate_response(result))?;
Ok(Async::Ready(Some(message)))
}
});
fn main() {
let handler = JrpcHandler::new().unwrap();
handler
.register_method("some/copyParams", SomeNotification::new().unwrap())
.and_then(|h| h.register_method("initialize", InitializeRequest::new().unwrap()))
.and_then(|h| {
h.handle_message(
r#"
{
"jsonrpc": "2.0",
"method": "some/copyParams",
"params": [42, 23],
"id": 531
}"#,
)
})
.and_then(|future| future.wait())
.and_then(|result| {
let result = result.unwrap();
assert_eq!(result.get_jsonrpc(), "2.0");
assert_eq!(
result.get_result(),
&Some(JsonValue::Array(vec![
JsonValue::Number(Number::from(42)),
JsonValue::Number(Number::from(23)),
]))
);
assert!(result.get_error().is_none());
assert_eq!(result.get_id(), &JsonValue::Number(Number::from(531)));
Ok(())
})
.unwrap();
}