From 212f0bb7aad019a77b7a158381a2dab5f9cfc4a6 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Mon, 11 Jan 2016 00:51:24 -0800 Subject: [PATCH] Fix issue where service fns with no args would cause compile errors --- src/lib.rs | 2 ++ src/macros.rs | 71 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 41d3fb0..9af0538 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,9 @@ //! } //! ``` +#![feature(trace_macros)] #![feature(const_fn)] +#![feature(braced_empty_structs)] #![feature(custom_derive, plugin)] #![plugin(serde_macros)] #![deny(missing_docs)] diff --git a/src/macros.rs b/src/macros.rs index 837200b..78c6176 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,4 +1,46 @@ -//! Provides a macro for creating an rpc service and client stub. +#[macro_export] +macro_rules! as_item { ($i:item) => {$i} } + +#[macro_export] +macro_rules! request_fns { + ($fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty) => ( + pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> { + let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*))); + let Reply::$fn_name(reply) = reply; + Ok(reply) + } + ); + ($( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty)*) => ( $( + pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> { + let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*))); + if let Reply::$fn_name(reply) = reply { + Ok(reply) + } else { + Err(Error::InternalError) + } + } + )*); +} + +#[macro_export] +macro_rules! define_request { + ($(@($($finished:tt)*))* --) => (as_item!( + #[allow(non_camel_case_types)] + #[derive(Debug, Serialize, Deserialize)] + enum Request { $($($finished)*),* } + );); + ($(@$finished:tt)* -- $name:ident() $($req:tt)*) => + (define_request!($(@$finished)* @($name) -- $($req)*);); + ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) => + (define_request!($(@$finished)* @($name $args) -- $($req)*);); + ($($started:tt)*) => (define_request!(-- $($started)*);); +} + +#[macro_export] +macro_rules! request_variant { + ($x:ident) => (Request::$x); + ($x:ident $($y:ident),+) => (Request::$x($($y),+)); +} #[macro_export] macro_rules! rpc_service { ($server:ident: @@ -49,13 +91,7 @@ macro_rules! rpc_service { ($server:ident: )* } - #[allow(non_camel_case_types)] - #[derive(Debug, Serialize, Deserialize)] - enum Request { - $( - $fn_name($($in_),*), - )* - } + define_request!($($fn_name($($in_),*))*); #[allow(non_camel_case_types)] #[derive(Debug, Serialize, Deserialize)] @@ -63,7 +99,6 @@ macro_rules! rpc_service { ($server:ident: $( $fn_name($out), )* - Impossible, } #[doc="The client stub that makes RPC calls to the server."] @@ -78,16 +113,7 @@ macro_rules! rpc_service { ($server:ident: Ok(Client(inner)) } - $( - pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> { - let reply = try!((self.0).rpc(&Request::$fn_name($($arg),*))); - if let Reply::$fn_name(reply) = reply { - Ok(reply) - } else { - Err(Error::InternalError) - } - } - )* + request_fns!($($fn_name($($arg: $in_),*) -> $out)*); } struct Server(S); @@ -98,7 +124,7 @@ macro_rules! rpc_service { ($server:ident: fn serve(&self, request: Request) -> Reply { match request { $( - Request::$fn_name($($arg),*) => + request_variant!($fn_name $($arg),*) => Reply::$fn_name((self.0).$fn_name($($arg),*)), )* } @@ -156,4 +182,9 @@ mod test { drop(client); shutdown.shutdown(); } + + // This is a test of a service with a fn that takes no args + rpc_service! {foo: + hello() -> String; + } }