diff --git a/Cargo.lock b/Cargo.lock index c0ddb40..2b7f99d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-jsonrpc" -version = "0.1.2" +version = "0.2.0" dependencies = [ "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -202,7 +202,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -217,7 +217,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.15.31" +version = "0.15.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -284,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" "checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" -"checksum syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a" +"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" diff --git a/Cargo.toml b/Cargo.toml index 94deaf6..c152ede 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-jsonrpc" -version = "0.1.3" +version = "0.2.0" authors = ["Victor Lopez "] edition = "2018" description = "Futures implementation for JSON-RPC" diff --git a/README.md b/README.md index 694077e..ddded17 100644 --- a/README.md +++ b/README.md @@ -23,30 +23,125 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -futures_jsonrpc = "0.1" +futures_jsonrpc = "0.2" ``` -## Examples +## Minimal example ```rust use futures_jsonrpc::futures::prelude::*; use futures_jsonrpc::*; use serde_json::Number; +use std::marker::PhantomData; + +// This macro will avoid some boilerplating, leaving only the `Future` implementation to be done +// +// Check for additional information in the detailed explanation below +generate_method_with_data_and_future!( + CopyParams, + 'r, + (String, i32, PhantomData<&'r ()>), + impl<'r> Future for CopyParams<'r> { + type Item = Option; + type Error = ErrorVariant; + + fn poll(&mut self) -> Result, Self::Error> { + let request = self.get_request()?; + let (_text, _value, _) = self.get_data(); + 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() { + // `JrpcHandler` instance is responsible for registering the JSON-RPC methods and receiving the + // requests. + // + // This is full `Arc`/`RwLock` protected. Therefore, it can be freely copied/sent among + // threads. + let handler = JrpcHandler::new().unwrap(); + + handler + // `register_method` will tie the method signature to an instance, not a generic. This + // means we can freely mutate this instance across different signatures. + .register_method("some/copyParams", CopyParams::new((String::new(), 15, PhantomData)).unwrap()) + + .and_then(|h| { + // `handle_message` will receive a raw implementation of `ToString` and return the + // associated future. If no future is found, an instance of + // `Err(ErrorVariant::MethodSignatureNotFound(String))` is returned + h.handle_message( + r#" + { + "jsonrpc": "2.0", + "method": "some/copyParams", + "params": [42, 23], + "id": 531 + }"#, + ) + }) + + // Just waiting for the poll of future. Check futures documentation. + .and_then(|future| future.wait()) + .and_then(|result| { + // The result is an instance of `JrpcResponse` + 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(); +} +``` + +## Detailed explanation + +```rust +use futures_jsonrpc::futures::prelude::*; +use futures_jsonrpc::*; +use std::marker::PhantomData; // `JrpcHandler` use foreign structures as controllers #[derive(Debug, Clone)] -struct SomeNotification { +pub struct CopyParams<'r> { request: Option, + data: (String, i32, PhantomData<&'r ()>), } -// Here is some boilerplate to instantiate a new Notification, and handle the received request -impl SomeNotification { - pub fn new() -> Result { +// This implementation is essentially some boilerplate to hold the data that may be used by the +// future poll +impl<'r> CopyParams<'r> { + // The `new` method will always receive a n-tuple as parameter to store data + // + // It is recommended to use atomic types, or `Arc` protected for heavy data. At every request, + // we `Clone` this struct to send it to the responsible thread + pub fn new(data: (String, i32, PhantomData<&'r ()>)) -> Result { let request = None; - let some_notification = SomeNotification { request }; + let some_notification = CopyParams { request, data }; Ok(some_notification) } + // The `get_data` will support the future poll with additional information that will not be + // available in the JsonRpc request + pub fn get_data(&self) -> &(String, i32, PhantomData<&'r ()>) { + &self.data + } + + // The `get_request` method will return the JsonRpc request to the future poll pub fn get_request(&self) -> Result { let request = self.request.clone(); request @@ -54,11 +149,14 @@ impl SomeNotification { .unwrap_or(Err(ErrorVariant::NoRequestProvided)) } + // This method is of internal usage to receive the request from `JrpcHandler` pub fn set_request(mut self, request: JrpcRequest) -> Result { self.request = Some(request); Ok(self) } + // This "fork" will be performed every time a new request is received, allowing async + // processing pub fn clone_with_request(&self, request: JrpcRequest) -> Result { self.clone().set_request(request) } @@ -69,7 +167,7 @@ impl SomeNotification { // The main implementation will go here // // Tokio provides very good documentation on futures. Check it: https://tokio.rs/ -impl Future for SomeNotification { +impl<'r> Future for CopyParams<'r> { // Optimally, we want to use JrpcResponse, for it is guaranteed to respect the JSON-RPC // specification. But, we can change the response here to something else, if required. type Item = Option; @@ -79,7 +177,11 @@ impl Future for SomeNotification { // We fetch the provided request to copy the data let request = self.get_request()?; - // The params, in this case, will be only a reflection on what was sent + // Here we can receive additional that that's not available in the request + let (_text, _value, _) = self.get_data(); + + // Do something with the request + // In this example, we are copying the parameters let params = request.get_params().clone().unwrap_or(JsonValue::Null); // `generate_response` will receive an enum `JrpcResponseParam` and reply @@ -94,106 +196,18 @@ impl Future for SomeNotification { // The handler will call this trait to spawn a new future and process it when a registered method // is requested. -impl JrpcMethodTrait for SomeNotification { +impl<'r> JrpcMethodTrait<'r> for CopyParams<'r> { // `generate_future` can generate any `Future` that respects the trait signature. This can be a // foreign structure, or just a copy of `self`, in case it implements `Future`. This can also // be a decision based on the received `JrpcRequest`. // // Since its not a reference, there are no restrictions. - fn generate_future<'a>( + fn generate_future( &self, request: JrpcRequest, - ) -> Result, Error = ErrorVariant>>, ErrorVariant> + ) -> Result, Error = ErrorVariant>>, ErrorVariant> { Ok(Box::new(self.clone_with_request(request)?)) } } - -// Or, alternitavely, we can use the `generate_method_with_future` macro to only implement the -// `Future` -generate_method_with_future!(InitializeRequest, impl Future for InitializeRequest { - type Item = Option; - type Error = ErrorVariant; - - fn poll(&mut self) -> Result, 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))) - } -}); - -// Also, we can use the `generate_method_with_data_and_future` macro to only implement the -// `Future` -generate_method_with_data_and_future!(SomeOtherRequest, (String, i32), impl Future for -SomeOtherRequest { - type Item = Option; - type Error = ErrorVariant; - - fn poll(&mut self) -> Result, Self::Error> { - let request = self.get_request()?; - let (text, value) = self.get_data(); - - let params = json!({ - "text": text, - "value": value, - }); - - let message = JrpcResponseParam::generate_result(params) - .and_then(|result| request.generate_response(result))?; - - Ok(Async::Ready(Some(message))) - } -}); - -fn main() { - // `JrpcHanlder` instance is responsible for registering the JSON-RPC methods and receiving the - // requests. - // - // This is full `Arc`/`RwLock` protected. Therefore, it can be freely copied/sent among - // threads. - let handler = JrpcHandler::new().unwrap(); - - handler - // `register_method` will tie the method signature to an instance, not a generic. This - // means we can freely mutate this instance across different signatures. - .register_method("some/copyParams", SomeNotification::new().unwrap()) - .and_then(|h| h.register_method("initialize", InitializeRequest::new().unwrap())) - .and_then(|h| { - // `handle_message` will receive a raw implementation of `ToString` and return the - // associated future. If no future is found, an instance of - // `Err(ErrorVariant::MethodSignatureNotFound(String))` is returned - h.handle_message( - r#" - { - "jsonrpc": "2.0", - "method": "some/copyParams", - "params": [42, 23], - "id": 531 - }"#, - ) - }) - // Just waiting for the poll of future. Check futures documentation. - .and_then(|future| future.wait()) - .and_then(|result| { - // The result is an instance of `JrpcResponse` - 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(); -} ``` diff --git a/src/handler.rs b/src/handler.rs index e016f69..c250a15 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; pub struct JrpcHandler<'a> { - hm_methods: Arc>>>, + hm_methods: Arc + 'a>>>>, } impl<'a> JrpcHandler<'a> { @@ -14,7 +14,7 @@ impl<'a> JrpcHandler<'a> { Ok(handler) } - pub fn register_method( + pub fn register_method + 'a>( &self, signature: T, jrpc_method: F, @@ -37,10 +37,10 @@ impl<'a> JrpcHandler<'a> { Ok(self) } - pub fn handle_message<'m, T: ToString>( + pub fn handle_message( &self, message: T, - ) -> Result, Error = ErrorVariant>>, ErrorVariant> + ) -> Result, Error = ErrorVariant>>, ErrorVariant> { let message = message.to_string(); let log_message = format!("Message {}", &message); diff --git a/src/lib.rs b/src/lib.rs index b2d37a2..1a55ff9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,30 +12,125 @@ //! //! ```toml //! [dependencies] -//! futures_jsonrpc = "0.1" +//! futures_jsonrpc = "0.2" //! ``` //! -//! ## Examples +//! ## Minimal example //! //! ``` //! use futures_jsonrpc::futures::prelude::*; //! use futures_jsonrpc::*; -//! use serde_json::{json, Number}; +//! use serde_json::Number; +//! use std::marker::PhantomData; +//! +//! // This macro will avoid some boilerplating, leaving only the `Future` implementation to be done +//! // +//! // Check for additional information in the detailed explanation below +//! generate_method_with_data_and_future!( +//! CopyParams, +//! 'r, +//! (String, i32, PhantomData<&'r ()>), +//! impl<'r> Future for CopyParams<'r> { +//! type Item = Option; +//! type Error = ErrorVariant; +//! +//! fn poll(&mut self) -> Result, Self::Error> { +//! let request = self.get_request()?; +//! let (_text, _value, _) = self.get_data(); +//! 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() { +//! // `JrpcHandler` instance is responsible for registering the JSON-RPC methods and receiving the +//! // requests. +//! // +//! // This is full `Arc`/`RwLock` protected. Therefore, it can be freely copied/sent among +//! // threads. +//! let handler = JrpcHandler::new().unwrap(); +//! +//! handler +//! // `register_method` will tie the method signature to an instance, not a generic. This +//! // means we can freely mutate this instance across different signatures. +//! .register_method("some/copyParams", CopyParams::new((String::new(), 15, PhantomData)).unwrap()) +//! +//! .and_then(|h| { +//! // `handle_message` will receive a raw implementation of `ToString` and return the +//! // associated future. If no future is found, an instance of +//! // `Err(ErrorVariant::MethodSignatureNotFound(String))` is returned +//! h.handle_message( +//! r#" +//! { +//! "jsonrpc": "2.0", +//! "method": "some/copyParams", +//! "params": [42, 23], +//! "id": 531 +//! }"#, +//! ) +//! }) +//! +//! // Just waiting for the poll of future. Check futures documentation. +//! .and_then(|future| future.wait()) +//! .and_then(|result| { +//! // The result is an instance of `JrpcResponse` +//! 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(); +//! } +//! ``` +//! +//! ## Detailed explanation +//! +//! ``` +//! use futures_jsonrpc::futures::prelude::*; +//! use futures_jsonrpc::*; +//! use std::marker::PhantomData; //! //! // `JrpcHandler` use foreign structures as controllers //! #[derive(Debug, Clone)] -//! struct SomeNotification { +//! pub struct CopyParams<'r> { //! request: Option, +//! data: (String, i32, PhantomData<&'r ()>), //! } //! -//! // Here is some boilerplate to instantiate a new Notification, and handle the received request -//! impl SomeNotification { -//! pub fn new() -> Result { +//! // This implementation is essentially some boilerplate to hold the data that may be used by the +//! // future poll +//! impl<'r> CopyParams<'r> { +//! // The `new` method will always receive a n-tuple as parameter to store data +//! // +//! // It is recommended to use atomic types, or `Arc` protected for heavy data. At every request, +//! // we `Clone` this struct to send it to the responsible thread +//! pub fn new(data: (String, i32, PhantomData<&'r ()>)) -> Result { //! let request = None; -//! let some_notification = SomeNotification { request }; +//! let some_notification = CopyParams { request, data }; //! Ok(some_notification) //! } //! +//! // The `get_data` will support the future poll with additional information that will not be +//! // available in the JsonRpc request +//! pub fn get_data(&self) -> &(String, i32, PhantomData<&'r ()>) { +//! &self.data +//! } +//! +//! // The `get_request` method will return the JsonRpc request to the future poll //! pub fn get_request(&self) -> Result { //! let request = self.request.clone(); //! request @@ -43,11 +138,14 @@ //! .unwrap_or(Err(ErrorVariant::NoRequestProvided)) //! } //! +//! // This method is of internal usage to receive the request from `JrpcHandler` //! pub fn set_request(mut self, request: JrpcRequest) -> Result { //! self.request = Some(request); //! Ok(self) //! } //! +//! // This "fork" will be performed every time a new request is received, allowing async +//! // processing //! pub fn clone_with_request(&self, request: JrpcRequest) -> Result { //! self.clone().set_request(request) //! } @@ -58,7 +156,7 @@ //! // The main implementation will go here //! // //! // Tokio provides very good documentation on futures. Check it: https://tokio.rs/ -//! impl Future for SomeNotification { +//! impl<'r> Future for CopyParams<'r> { //! // Optimally, we want to use JrpcResponse, for it is guaranteed to respect the JSON-RPC //! // specification. But, we can change the response here to something else, if required. //! type Item = Option; @@ -68,7 +166,11 @@ //! // We fetch the provided request to copy the data //! let request = self.get_request()?; //! -//! // The params, in this case, will be only a reflection on what was sent +//! // Here we can receive additional that that's not available in the request +//! let (_text, _value, _) = self.get_data(); +//! +//! // Do something with the request +//! // In this example, we are copying the parameters //! let params = request.get_params().clone().unwrap_or(JsonValue::Null); //! //! // `generate_response` will receive an enum `JrpcResponseParam` and reply @@ -83,108 +185,20 @@ //! //! // The handler will call this trait to spawn a new future and process it when a registered method //! // is requested. -//! impl JrpcMethodTrait for SomeNotification { +//! impl<'r> JrpcMethodTrait<'r> for CopyParams<'r> { //! // `generate_future` can generate any `Future` that respects the trait signature. This can be a //! // foreign structure, or just a copy of `self`, in case it implements `Future`. This can also //! // be a decision based on the received `JrpcRequest`. //! // //! // Since its not a reference, there are no restrictions. -//! fn generate_future<'a>( +//! fn generate_future( //! &self, //! request: JrpcRequest, -//! ) -> Result, Error = ErrorVariant>>, ErrorVariant> +//! ) -> Result, Error = ErrorVariant>>, ErrorVariant> //! { //! Ok(Box::new(self.clone_with_request(request)?)) //! } //! } -//! -//! // Or, alternitavely, we can use the `generate_method_with_future` macro to only implement the -//! // `Future` -//! generate_method_with_future!(InitializeRequest, impl Future for InitializeRequest { -//! type Item = Option; -//! type Error = ErrorVariant; -//! -//! fn poll(&mut self) -> Result, 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))) -//! } -//! }); -//! -//! // Also, we can use the `generate_method_with_data_and_future` macro to only implement the -//! // `Future` -//! generate_method_with_data_and_future!(SomeOtherRequest, (String, i32), impl Future for -//! SomeOtherRequest { -//! type Item = Option; -//! type Error = ErrorVariant; -//! -//! fn poll(&mut self) -> Result, Self::Error> { -//! let request = self.get_request()?; -//! let (text, value) = self.get_data(); -//! -//! let params = json!({ -//! "text": text, -//! "value": value, -//! }); -//! -//! let message = JrpcResponseParam::generate_result(params) -//! .and_then(|result| request.generate_response(result))?; -//! -//! Ok(Async::Ready(Some(message))) -//! } -//! }); -//! -//! fn main() { -//! // `JrpcHanlder` instance is responsible for registering the JSON-RPC methods and receiving the -//! // requests. -//! // -//! // This is full `Arc`/`RwLock` protected. Therefore, it can be freely copied/sent among -//! // threads. -//! let handler = JrpcHandler::new().unwrap(); -//! -//! handler -//! // `register_method` will tie the method signature to an instance, not a generic. This -//! // means we can freely mutate this instance across different signatures. -//! .register_method("some/copyParams", SomeNotification::new().unwrap()) -//! .and_then(|h| h.register_method("initialize", InitializeRequest::new().unwrap())) -//! .and_then(|h| { -//! // `handle_message` will receive a raw implementation of `ToString` and return the -//! // associated future. If no future is found, an instance of -//! // `Err(ErrorVariant::MethodSignatureNotFound(String))` is returned -//! h.handle_message( -//! r#" -//! { -//! "jsonrpc": "2.0", -//! "method": "some/copyParams", -//! "params": [42, 23], -//! "id": 531 -//! }"#, -//! ) -//! }) -//! // Just waiting for the poll of future. Check futures documentation. -//! .and_then(|future| future.wait()) -//! .and_then(|result| { -//! // The result is an instance of `JrpcResponse` -//! 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(); -//! } //! ``` #[macro_use] @@ -224,75 +238,28 @@ impl fmt::Display for ErrorVariant { ErrorVariant::MethodSignatureNotFound(s) => { write!(f, "Method signature '{}' not found", s) } - ErrorVariant::InternalErrorMessage(s) => { - write!(f, "An error ocurred: {}", s) - } + ErrorVariant::InternalErrorMessage(s) => write!(f, "An error ocurred: {}", s), _ => write!(f, "{:?}", self), } } } -#[macro_export] -macro_rules! generate_method_with_future { - ($struct_identifier:ident, $future:item) => { - #[derive(Debug, Clone)] - pub struct $struct_identifier { - request: Option, - } - - impl $struct_identifier { - pub fn new() -> Result { - let request = None; - let some_notification = $struct_identifier { request }; - Ok(some_notification) - } - - pub fn get_request(&self) -> Result { - 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.request = Some(request); - Ok(self) - } - - pub fn clone_with_request(&self, request: JrpcRequest) -> Result { - self.clone().set_request(request) - } - } - - $future - - impl JrpcMethodTrait for $struct_identifier { - fn generate_future<'a>( - &self, - request: JrpcRequest, - ) -> Result< - Box<'a + Future, Error = ErrorVariant>>, - ErrorVariant, - > { - Ok(Box::new(self.clone_with_request(request)?)) - } - } - }; -} - #[macro_export] macro_rules! generate_method_with_data_and_future { - ($struct_identifier:ident, $data:ty, $future:item) => { + ($struct_identifier:ident, $lifetime:tt, $data:ty, $future:item) => { #[derive(Debug, Clone)] - pub struct $struct_identifier { + pub struct $struct_identifier<$lifetime> { request: Option, data: $data, } - impl $struct_identifier { + impl<$lifetime> $struct_identifier<$lifetime> { pub fn new(data: $data) -> Result { let request = None; - let some_notification = $struct_identifier { request, data }; + let some_notification = $struct_identifier { + request, + data, + }; Ok(some_notification) } @@ -319,12 +286,12 @@ macro_rules! generate_method_with_data_and_future { $future - impl JrpcMethodTrait for $struct_identifier { - fn generate_future<'a>( + impl<$lifetime> JrpcMethodTrait<$lifetime> for $struct_identifier<$lifetime> { + fn generate_future( &self, request: JrpcRequest, ) -> Result< - Box<'a + Future, Error = ErrorVariant>>, + Box<$lifetime + Future, Error = ErrorVariant>>, ErrorVariant, > { Ok(Box::new(self.clone_with_request(request)?)) diff --git a/src/method.rs b/src/method.rs index 3173bd2..3ab5c0d 100644 --- a/src/method.rs +++ b/src/method.rs @@ -1,8 +1,8 @@ use crate::futures::prelude::*; use crate::{ErrorVariant, JrpcRequest, JrpcResponse}; -pub trait JrpcMethodTrait { - fn generate_future<'a>( +pub trait JrpcMethodTrait<'a> { + fn generate_future( &self, request: JrpcRequest, ) -> Result, Error = ErrorVariant>>, ErrorVariant>; diff --git a/src/parser.rs b/src/parser.rs index 8f05965..e6a6f54 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -7,10 +7,10 @@ pub struct JrpcRequest { jsonrpc: String, method: String, - #[serde(skip_serializing_if="Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none")] params: Option, - #[serde(skip_serializing_if="Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none")] id: Option, } @@ -135,10 +135,10 @@ impl JrpcResponseParam { pub struct JrpcResponse { jsonrpc: String, - #[serde(skip_serializing_if="Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none")] result: Option, - #[serde(skip_serializing_if="Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none")] error: Option, id: JsonValue,