From b0319e7db96aa85f5a9b5a1eb14eb47dd5cddf91 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Tue, 30 Jul 2019 00:51:29 -0700 Subject: [PATCH] Remove macros.rs --- tarpc/src/macros.rs | 355 -------------------------------------------- 1 file changed, 355 deletions(-) delete mode 100644 tarpc/src/macros.rs diff --git a/tarpc/src/macros.rs b/tarpc/src/macros.rs deleted file mode 100644 index 2856f10..0000000 --- a/tarpc/src/macros.rs +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2018 Google LLC -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file or at -// https://opensource.org/licenses/MIT. - -#[cfg(feature = "serde")] -#[doc(hidden)] -#[macro_export] -macro_rules! add_serde_if_enabled { - ($(#[$attr:meta])* -- $i:item) => { - $(#[$attr])* - #[derive($crate::serde::Serialize, $crate::serde::Deserialize)] - $i - } -} - -#[cfg(not(feature = "serde"))] -#[doc(hidden)] -#[macro_export] -macro_rules! add_serde_if_enabled { - ($(#[$attr:meta])* -- $i:item) => { - $(#[$attr])* - $i - } -} - -/// The main macro that creates RPC services. -/// -/// Rpc methods are specified, mirroring trait syntax: -/// -/// ``` -/// # #![feature(async_await, proc_macro_hygiene)] -/// # fn main() {} -/// # tarpc::service! { -/// /// Say hello -/// rpc hello(name: String) -> String; -/// # } -/// ``` -/// -/// Attributes can be attached to each rpc. These attributes -/// will then be attached to the generated service traits' -/// corresponding `fn`s, as well as to the client stubs' RPCs. -/// -/// The following items are expanded in the enclosing module: -/// -/// * `trait Service` -- defines the RPC service. -/// * `fn serve` -- turns a service impl into a request handler. -/// * `Client` -- a client stub with a fn for each RPC. -/// * `fn new_stub` -- creates a new Client stub. -/// -#[macro_export] -macro_rules! service { - () => { - compile_error!("Must define at least one RPC method."); - }; -// Entry point - ( - $( - $(#[$attr:meta])* - rpc $fn_name:ident( $( $(#[$argattr:meta])* $arg:ident : $in_:ty ),* ) $(-> $out:ty)*; - )* - ) => { - $crate::service! {{ - $( - $(#[$attr])* - rpc $fn_name( $( $(#[$argattr])* $arg : $in_ ),* ) $(-> $out)*; - )* - }} - }; -// Pattern for when the next rpc has an implicit unit return type. - ( - { - $(#[$attr:meta])* - rpc $fn_name:ident( $( $(#[$argattr:meta])* $arg:ident : $in_:ty ),* ); - - $( $unexpanded:tt )* - } - $( $expanded:tt )* - ) => { - $crate::service! { - { $( $unexpanded )* } - - $( $expanded )* - - $(#[$attr])* - rpc $fn_name( $( $(#[$argattr])* $arg : $in_ ),* ) -> (); - } - }; -// Pattern for when the next rpc has an explicit return type. - ( - { - $(#[$attr:meta])* - rpc $fn_name:ident( $( $(#[$argattr:meta])* $arg:ident : $in_:ty ),* ) -> $out:ty; - - $( $unexpanded:tt )* - } - $( $expanded:tt )* - ) => { - $crate::service! { - { $( $unexpanded )* } - - $( $expanded )* - - $(#[$attr])* - rpc $fn_name( $( $(#[$argattr])* $arg : $in_ ),* ) -> $out; - } - }; -// Pattern for when all return types have been expanded - ( - { } // none left to expand - $( - $(#[$attr:meta])* - rpc $fn_name:ident ( $( $(#[$argattr:meta])* $arg:ident : $in_:ty ),* ) -> $out:ty; - )* - ) => { - $crate::add_serde_if_enabled! { - /// The request sent over the wire from the client to the server. - #[derive(Debug)] - #[allow(non_camel_case_types, unused)] - -- - pub enum Request { - $( - $(#[$attr])* - $fn_name{ $( $(#[$argattr])* $arg: $in_,)* } - ),* - } - } - - $crate::add_serde_if_enabled! { - /// The response sent over the wire from the server to the client. - #[derive(Debug)] - #[allow(non_camel_case_types, unused)] - -- - pub enum Response { - $( - $(#[$attr])* - $fn_name($out) - ),* - } - } - - // TODO: proc_macro can't currently parse $crate, so this needs to be imported for the - // usage of snake_to_camel! to work. - use $crate::futures::Future as Future__; - - /// Defines the RPC service. The additional trait bounds are required so that services can - /// multiplex requests across multiple tasks, potentially on multiple threads. - pub trait Service: Clone + Send + 'static { - $( - $crate::snake_to_camel! { - /// The type of future returned by `{}`. - type $fn_name: Future__ + Send; - } - - $(#[$attr])* - fn $fn_name(self, ctx: $crate::context::Context, $($arg:$in_),*) -> $crate::ty_snake_to_camel!(Self::$fn_name); - )* - } - - // TODO: use an existential type instead of this when existential types work. - /// A future resolving to a server [`Response`]. - #[allow(non_camel_case_types)] - pub enum ResponseFut { - $( - $(#[$attr])* - $fn_name($crate::ty_snake_to_camel!(::$fn_name)), - )* - } - - impl ::std::fmt::Debug for ResponseFut { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.debug_struct("Response").finish() - } - } - - impl ::std::future::Future for ResponseFut { - type Output = ::std::io::Result; - - fn poll(self: ::std::pin::Pin<&mut Self>, cx: &mut ::std::task::Context<'_>) - -> ::std::task::Poll<::std::io::Result> - { - unsafe { - match ::std::pin::Pin::get_unchecked_mut(self) { - $( - ResponseFut::$fn_name(resp) => - ::std::pin::Pin::new_unchecked(resp) - .poll(cx) - .map(Response::$fn_name) - .map(Ok), - )* - } - } - } - } - - /// Returns a serving function to use with rpc::server::Server. - pub fn serve(service: S) - -> impl FnOnce($crate::context::Context, Request) -> ResponseFut + Send + 'static + Clone { - move |ctx, req| { - match req { - $( - Request::$fn_name{ $($arg,)* } => { - let resp = Service::$fn_name(service.clone(), ctx, $($arg),*); - ResponseFut::$fn_name(resp) - } - )* - } - } - } - - #[allow(unused)] - #[derive(Clone, Debug)] - /// The client stub that makes RPC calls to the server. Exposes a Future interface. - pub struct Client>(C); - - /// Returns a new client stub that sends requests over the given transport. - pub async fn new_stub(config: $crate::client::Config, transport: T) - -> ::std::io::Result - where - T: $crate::Transport<$crate::ClientMessage, $crate::Response> + Send + 'static, - { - Ok(Client($crate::client::new(config, transport).await?)) - } - - impl From for Client - where for <'a> C: $crate::Client<'a, Request, Response = Response> - { - fn from(client: C) -> Self { - Client(client) - } - } - - impl Client - where for<'a> C: $crate::Client<'a, Request, Response = Response> - { - $( - #[allow(unused)] - $(#[$attr])* - pub fn $fn_name(&mut self, ctx: $crate::context::Context, $($arg: $in_),*) - -> impl ::std::future::Future> + '_ { - let request__ = Request::$fn_name { $($arg,)* }; - let resp = $crate::Client::call(&mut self.0, ctx, request__); - async move { - match resp.await? { - Response::$fn_name(msg__) => ::std::result::Result::Ok(msg__), - _ => unreachable!(), - } - } - } - )* - } - } -} - -// allow dead code; we're just testing that the macro expansion compiles -#[allow(dead_code)] -#[cfg(test)] -mod syntax_test { - service! { - #[deny(warnings)] - #[allow(non_snake_case)] - rpc TestCamelCaseDoesntConflict(); - rpc hello() -> String; - #[doc="attr"] - rpc attr(s: String) -> String; - rpc no_args_no_return(); - rpc no_args() -> (); - rpc one_arg(foo: String) -> i32; - rpc two_args_no_return(bar: String, baz: u64); - rpc two_args(bar: String, baz: u64) -> String; - rpc no_args_ret_error() -> i32; - rpc one_arg_ret_error(foo: String) -> String; - rpc no_arg_implicit_return_error(); - #[doc="attr"] - rpc one_arg_implicit_return_error(foo: String); - } -} - -#[cfg(test)] -mod functional_test { - use futures::{ - future::{ready, Ready}, - prelude::*, - }; - use rpc::{client, context, server::Handler, transport::channel}; - - service! { - rpc add(x: i32, y: i32) -> i32; - rpc hey(name: String) -> String; - } - - #[derive(Clone)] - struct Server; - - impl Service for Server { - type AddFut = Ready; - - fn add(self, _: context::Context, x: i32, y: i32) -> Self::AddFut { - ready(x + y) - } - - type HeyFut = Ready; - - fn hey(self, _: context::Context, name: String) -> Self::HeyFut { - ready(format!("Hey, {}.", name)) - } - } - - #[runtime::test(runtime_tokio::TokioCurrentThread)] - async fn sequential() { - let _ = env_logger::try_init(); - - let (tx, rx) = channel::unbounded(); - let _ = runtime::spawn( - crate::Server::default() - .incoming(stream::once(ready(rx))) - .respond_with(serve(Server)), - ); - - let mut client = new_stub(client::Config::default(), tx).await.unwrap(); - assert_eq!(3, client.add(context::current(), 1, 2).await.unwrap()); - assert_eq!( - "Hey, Tim.", - client - .hey(context::current(), "Tim".to_string()) - .await - .unwrap() - ); - } - - #[runtime::test(runtime_tokio::TokioCurrentThread)] - async fn concurrent() { - let _ = env_logger::try_init(); - - let (tx, rx) = channel::unbounded(); - let _ = runtime::spawn( - rpc::Server::default() - .incoming(stream::once(ready(rx))) - .respond_with(serve(Server)), - ); - - let client = new_stub(client::Config::default(), tx).await.unwrap(); - let mut c = client.clone(); - let req1 = c.add(context::current(), 1, 2); - let mut c = client.clone(); - let req2 = c.add(context::current(), 3, 4); - let mut c = client.clone(); - let req3 = c.hey(context::current(), "Tim".to_string()); - - assert_eq!(3, req1.await.unwrap()); - assert_eq!(7, req2.await.unwrap()); - assert_eq!("Hey, Tim.", req3.await.unwrap()); - } -}