From 3c1fd8d46a7de1cda1effbc433e95171d86dc38d Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 10 Dec 2016 01:25:15 +0100 Subject: [PATCH 1/2] use jsonrpc-macros, fixes #277 --- Cargo.lock | 15 +- rpc/Cargo.toml | 2 + rpc/src/lib.rs | 2 + rpc/src/v1/helpers/auto_args.rs | 294 -------------------------------- rpc/src/v1/helpers/errors.rs | 14 +- rpc/src/v1/helpers/mod.rs | 4 - rpc/src/v1/helpers/params.rs | 11 -- rpc/src/v1/traits/miner.rs | 1 - rpc/src/v1/traits/raw.rs | 1 - 9 files changed, 18 insertions(+), 326 deletions(-) delete mode 100644 rpc/src/v1/helpers/auto_args.rs delete mode 100644 rpc/src/v1/helpers/params.rs diff --git a/Cargo.lock b/Cargo.lock index 51fa8d81..afee93d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,7 +331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "4.0.0" -source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53" +source = "git+https://github.com/ethcore/jsonrpc.git#19a225edce9069ebc0da784059b34e0e6c9b4834" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -343,7 +343,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc.git#1500da1b9613a0a17fc0109d825f3ccc60199a53" +source = "git+https://github.com/ethcore/jsonrpc.git#19a225edce9069ebc0da784059b34e0e6c9b4834" dependencies = [ "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", @@ -351,6 +351,15 @@ dependencies = [ "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-macros" +version = "0.1.0" +source = "git+https://github.com/ethcore/jsonrpc.git#19a225edce9069ebc0da784059b34e0e6c9b4834" +dependencies = [ + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -804,6 +813,7 @@ dependencies = [ "db 0.1.0", "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miner 0.1.0", "network 0.1.0", @@ -1250,6 +1260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-macros 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 3d677e74..0f4a1607 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -14,7 +14,9 @@ rustc-serialize = "0.3" tokio-core = "0.1.1" serde_macros = { version = "0.8.0", optional = true } jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } + sync = { path = "../sync" } serialization = { path = "../serialization" } chain = { path = "../chain" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index e061b965..a74c2be7 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -6,6 +6,8 @@ extern crate rustc_serialize; extern crate serde; extern crate serde_json; extern crate jsonrpc_core; +#[macro_use] +extern crate jsonrpc_macros; extern crate jsonrpc_http_server; extern crate tokio_core; extern crate sync; diff --git a/rpc/src/v1/helpers/auto_args.rs b/rpc/src/v1/helpers/auto_args.rs deleted file mode 100644 index f60f7425..00000000 --- a/rpc/src/v1/helpers/auto_args.rs +++ /dev/null @@ -1,294 +0,0 @@ -// because we reuse the type names as idents in the macros as a dirty hack to -// work around `concat_idents!` being unstable. -#![allow(non_snake_case)] - -///! Automatically serialize and deserialize parameters around a strongly-typed function. - -use super::errors; - -use jsonrpc_core::{Error, Params, Value, from_params, to_value}; -use serde::{Serialize, Deserialize}; - -/// Auto-generates an RPC trait from trait definition. -/// -/// This just copies out all the methods, docs, and adds another -/// function `to_delegate` which will automatically wrap each strongly-typed -/// function in a wrapper which handles parameter and output type serialization. -/// -/// RPC functions may come in a couple forms: async and synchronous. -/// These are parsed with the custom `#[rpc]` attribute, which must follow -/// documentation. -/// -/// ## The #[rpc] attribute -/// -/// Valid forms: -/// - `#[rpc(name = "name_here")]` (a synchronous rpc function which should be bound to the given name) -/// - `#[rpc(async, name = "name_here")]` (an async rpc function which should be bound to the given name) -/// -/// Synchronous function format: -/// `fn foo(&self, Param1, Param2, Param3) -> Out`. -/// -/// Asynchronous RPC functions must come in this form: -/// `fn foo(&self, Param1, Param2, Param3, Ready); -/// -/// Anything else will be rejected by the code generator. -macro_rules! build_rpc_trait { - // entry-point. todo: make another for traits w/ bounds. - ( - $(#[$t_attr: meta])* - pub trait $name: ident { - $( - $( #[doc=$m_doc:expr] )* - #[ rpc( $($t:tt)* ) ] - fn $m_name: ident ( $($p: tt)* ) $( -> Result<$out: ty, Error> )* ; - )* - } - ) => { - $(#[$t_attr])* - pub trait $name: Sized + Send + Sync + 'static { - $( - $(#[doc=$m_doc])* - fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* ; - )* - - /// Transform this into an `IoDelegate`, automatically wrapping - /// the parameters. - fn to_delegate(self) -> ::jsonrpc_core::IoDelegate { - let mut del = ::jsonrpc_core::IoDelegate::new(self.into()); - $( - build_rpc_trait!(WRAP del => - ( $($t)* ) - fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* - ); - )* - del - } - } - }; - - ( WRAP $del: expr => - (name = $name: expr) - fn $method: ident (&self $(, $param: ty)*) -> Result<$out: ty, Error> - ) => { - $del.add_method($name, move |base, params| { - (Self::$method as fn(&_ $(, $param)*) -> Result<$out, Error>).wrap_rpc(base, params) - }) - }; - - ( WRAP $del: expr => - (async, name = $name: expr) - fn $method: ident (&self, Ready<$out: ty> $(, $param: ty)*) - ) => { - $del.add_async_method($name, move |base, params, ready| { - (Self::$method as fn(&_, Ready<$out> $(, $param)*)).wrap_rpc(base, params, ready) - }) - }; -} - -/// A wrapper type without an implementation of `Deserialize` -/// which allows a special implementation of `Wrap` for functions -/// that take a trailing default parameter. -pub struct Trailing(pub T); - -/// A wrapper type for `jsonrpc_core`'s weakly-typed `Ready` struct. -pub struct Ready { - inner: ::jsonrpc_core::Ready, - _marker: ::std::marker::PhantomData, -} - -impl From<::jsonrpc_core::Ready> for Ready { - fn from(ready: ::jsonrpc_core::Ready) -> Self { - Ready { inner: ready, _marker: ::std::marker::PhantomData } - } -} - -impl Ready { - /// Respond withthe asynchronous result. - pub fn ready(self, result: Result) { - self.inner.ready(result.map(to_value)) - } -} - -/// Wrapper trait for synchronous RPC functions. -pub trait Wrap { - fn wrap_rpc(&self, base: &B, params: Params) -> Result; -} - -/// Wrapper trait for asynchronous RPC functions. -pub trait WrapAsync { - fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready); -} - -// special impl for no parameters. -impl Wrap for fn(&B) -> Result - where B: Send + Sync + 'static, OUT: Serialize -{ - fn wrap_rpc(&self, base: &B, params: Params) -> Result { - ::v1::helpers::params::expect_no_params(params) - .and_then(|()| (self)(base)) - .map(to_value) - } -} - -impl WrapAsync for fn(&B, Ready) - where B: Send + Sync + 'static, OUT: Serialize -{ - fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) { - match ::v1::helpers::params::expect_no_params(params) { - Ok(()) => (self)(base, ready.into()), - Err(e) => ready.ready(Err(e)), - } - } -} - -// creates a wrapper implementation which deserializes the parameters, -// calls the function with concrete type, and serializes the output. -macro_rules! wrap { - ($($x: ident),+) => { - - // synchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - > Wrap for fn(&BASE, $($x,)+) -> Result { - fn wrap_rpc(&self, base: &BASE, params: Params) -> Result { - from_params::<($($x,)+)>(params).and_then(|($($x,)+)| { - (self)(base, $($x,)+) - }).map(to_value) - } - } - - // asynchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - > WrapAsync for fn(&BASE, Ready, $($x,)+ ) { - fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) { - match from_params::<($($x,)+)>(params) { - Ok(($($x,)+)) => (self)(base, ready.into(), $($x,)+), - Err(e) => ready.ready(Err(e)), - } - } - } - } -} - -// special impl for no parameters other than block parameter. -impl Wrap for fn(&B, Trailing) -> Result - where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize -{ - fn wrap_rpc(&self, base: &B, params: Params) -> Result { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return Err(errors::invalid_params("not an array", "")), - }; - - let (id,) = match len { - 0 => (T::default(),), - 1 => try!(from_params::<(T,)>(params)), - _ => return Err(Error::invalid_params()), - }; - - (self)(base, Trailing(id)).map(to_value) - } -} - -impl WrapAsync for fn(&B, Ready, Trailing) - where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize -{ - fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return ready.ready(Err(errors::invalid_params("not an array", ""))), - }; - - let id = match len { - 0 => Ok((T::default(),)), - 1 => from_params::<(T,)>(params), - _ => Err(Error::invalid_params()), - }; - - match id { - Ok((id,)) => (self)(base, ready.into(), Trailing(id)), - Err(e) => ready.ready(Err(e)), - } - } -} - -// similar to `wrap!`, but handles a single default trailing parameter -// accepts an additional argument indicating the number of non-trailing parameters. -macro_rules! wrap_with_trailing { - ($num: expr, $($x: ident),+) => { - // synchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - TRAILING: Default + Deserialize, - > Wrap for fn(&BASE, $($x,)+ Trailing) -> Result { - fn wrap_rpc(&self, base: &BASE, params: Params) -> Result { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return Err(errors::invalid_params("not an array", "")), - }; - - let params = match len - $num { - 0 => from_params::<($($x,)+)>(params) - .map(|($($x,)+)| ($($x,)+ TRAILING::default())), - 1 => from_params::<($($x,)+ TRAILING)>(params) - .map(|($($x,)+ id)| ($($x,)+ id)), - _ => Err(Error::invalid_params()), - }; - - let ($($x,)+ id) = try!(params); - (self)(base, $($x,)+ Trailing(id)).map(to_value) - } - } - - // asynchronous implementation - impl < - BASE: Send + Sync + 'static, - OUT: Serialize, - $($x: Deserialize,)+ - TRAILING: Default + Deserialize, - > WrapAsync for fn(&BASE, Ready, $($x,)+ Trailing) { - fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) { - let len = match params { - Params::Array(ref v) => v.len(), - Params::None => 0, - _ => return ready.ready(Err(errors::invalid_params("not an array", ""))), - }; - - let params = match len - $num { - 0 => from_params::<($($x,)+)>(params) - .map(|($($x,)+)| ($($x,)+ TRAILING::default())), - 1 => from_params::<($($x,)+ TRAILING)>(params) - .map(|($($x,)+ id)| ($($x,)+ id)), - _ => Err(Error::invalid_params()), - }; - - match params { - Ok(($($x,)+ id)) => (self)(base, ready.into(), $($x,)+ Trailing(id)), - Err(e) => ready.ready(Err(e)) - } - } - } - } -} - -wrap!(A, B, C, D, E); -wrap!(A, B, C, D); -wrap!(A, B, C); -wrap!(A, B); -wrap!(A); - -wrap_with_trailing!(5, A, B, C, D, E); -wrap_with_trailing!(4, A, B, C, D); -wrap_with_trailing!(3, A, B, C); -wrap_with_trailing!(2, A, B); -wrap_with_trailing!(1, A); diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 90ab238f..74ac6c57 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -5,22 +5,9 @@ mod codes { pub const EXECUTION_ERROR: i64 = -32015; } - -macro_rules! rpc_unimplemented { - () => (Err(::v1::helpers::errors::unimplemented(None))) -} - use std::fmt; use jsonrpc_core::{Error, ErrorCode, Value}; -pub fn unimplemented(details: Option) -> Error { - Error { - code: ErrorCode::InternalError, - message: "This request is not implemented yet. Please create an issue on Github repo.".into(), - data: details.map(Value::String), - } -} - pub fn invalid_params(param: &str, details: T) -> Error { Error { code: ErrorCode::InvalidParams, @@ -36,3 +23,4 @@ pub fn execution(data: T) -> Error { data: Some(Value::String(format!("{:?}", data))), } } + diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index d2f54233..629e98fb 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -1,5 +1 @@ -#[macro_use] -pub mod auto_args; -#[macro_use] pub mod errors; -mod params; diff --git a/rpc/src/v1/helpers/params.rs b/rpc/src/v1/helpers/params.rs deleted file mode 100644 index c0ea9c10..00000000 --- a/rpc/src/v1/helpers/params.rs +++ /dev/null @@ -1,11 +0,0 @@ -///! Parameters parsing helpers - -use jsonrpc_core::{Error, Params}; -use v1::helpers::errors; - -pub fn expect_no_params(params: Params) -> Result<(), Error> { - match params { - Params::None => Ok(()), - p => Err(errors::invalid_params("No parameters were expected", p)), - } -} diff --git a/rpc/src/v1/traits/miner.rs b/rpc/src/v1/traits/miner.rs index 32d371e9..c3c47194 100644 --- a/rpc/src/v1/traits/miner.rs +++ b/rpc/src/v1/traits/miner.rs @@ -1,6 +1,5 @@ use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; use v1::types::{BlockTemplate, BlockTemplateRequest}; build_rpc_trait! { diff --git a/rpc/src/v1/traits/raw.rs b/rpc/src/v1/traits/raw.rs index 3295353b..3406083c 100644 --- a/rpc/src/v1/traits/raw.rs +++ b/rpc/src/v1/traits/raw.rs @@ -1,6 +1,5 @@ use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; use v1::types::RawTransaction; use v1::types::H256; From d8f6dbea861dcdd4bd956b760304cfc7059fd41a Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 10 Dec 2016 02:07:29 +0100 Subject: [PATCH 2/2] use just one version of parking_lot --- Cargo.lock | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afee93d9..e242b4f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,10 +331,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "4.0.0" -source = "git+https://github.com/ethcore/jsonrpc.git#19a225edce9069ebc0da784059b34e0e6c9b4834" +source = "git+https://github.com/ethcore/jsonrpc.git#140257f1a726e9190bdaafeb4625b2a5400de4da" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -343,7 +343,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc.git#19a225edce9069ebc0da784059b34e0e6c9b4834" +source = "git+https://github.com/ethcore/jsonrpc.git#140257f1a726e9190bdaafeb4625b2a5400de4da" dependencies = [ "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", @@ -354,7 +354,7 @@ dependencies = [ [[package]] name = "jsonrpc-macros" version = "0.1.0" -source = "git+https://github.com/ethcore/jsonrpc.git#19a225edce9069ebc0da784059b34e0e6c9b4834" +source = "git+https://github.com/ethcore/jsonrpc.git#140257f1a726e9190bdaafeb4625b2a5400de4da" dependencies = [ "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "serde 0.8.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -641,17 +641,6 @@ dependencies = [ "tokio-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" version = "0.3.6" @@ -1286,7 +1275,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" -"checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6" "checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621" "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" "checksum quasi 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94a532453b931a4483a5b2e40f0fe04aee35b6bc2c0eeec876f1bd2358a134d3"