From 4dfb3a48c33dfa2e05915c80c3189e8c4e2ac851 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 18 Jul 2017 12:04:56 -0700 Subject: [PATCH] Derive Deserialize, Serialize in macros. Requires feature(use_extern_macros). (#151) --- README.md | 6 +- benches/latency.rs | 2 +- examples/concurrency.rs | 2 +- examples/pubsub.rs | 2 +- examples/readme_errors.rs | 2 +- examples/readme_futures.rs | 2 +- examples/readme_sync.rs | 2 +- examples/server_calling_server.rs | 2 +- examples/sync_server_calling_server.rs | 2 +- examples/throughput.rs | 2 +- examples/two_clients.rs | 2 +- src/lib.rs | 11 +- src/macros.rs | 171 ++----------------------- 13 files changed, 27 insertions(+), 181 deletions(-) diff --git a/README.md b/README.md index 3b8ac46..4fc7b08 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ tarpc has two APIs: `sync` for blocking code and `future` for asynchronous code. Here's how to use the sync api. ```rust -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] #[macro_use] @@ -100,7 +100,7 @@ races! See the `tarpc_examples` package for more examples. Here's the same service, implemented using futures. ```rust -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate futures; @@ -171,7 +171,7 @@ However, if you are working with both stream types, ensure that you use the TLS servers and TCP clients with TCP servers. ```rust,no_run -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate futures; diff --git a/benches/latency.rs b/benches/latency.rs index 79bd220..a60bb62 100644 --- a/benches/latency.rs +++ b/benches/latency.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin, test)] +#![feature(plugin, test, use_extern_macros)] #![plugin(tarpc_plugins)] #[macro_use] diff --git a/examples/concurrency.rs b/examples/concurrency.rs index 202b366..451fb10 100644 --- a/examples/concurrency.rs +++ b/examples/concurrency.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(inclusive_range_syntax, conservative_impl_trait, plugin, never_type)] +#![feature(inclusive_range_syntax, conservative_impl_trait, plugin, never_type, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate chrono; diff --git a/examples/pubsub.rs b/examples/pubsub.rs index a30ebe1..37b0a39 100644 --- a/examples/pubsub.rs +++ b/examples/pubsub.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate env_logger; diff --git a/examples/readme_errors.rs b/examples/readme_errors.rs index 5d33b68..625f81d 100644 --- a/examples/readme_errors.rs +++ b/examples/readme_errors.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate futures; diff --git a/examples/readme_futures.rs b/examples/readme_futures.rs index 3451e27..3d942c6 100644 --- a/examples/readme_futures.rs +++ b/examples/readme_futures.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate futures; diff --git a/examples/readme_sync.rs b/examples/readme_sync.rs index f19758b..060c717 100644 --- a/examples/readme_sync.rs +++ b/examples/readme_sync.rs @@ -4,7 +4,7 @@ // This file may not be copied, modified, or distributed except according to those terms. // required by `FutureClient` (not used directly in this example) -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate futures; diff --git a/examples/server_calling_server.rs b/examples/server_calling_server.rs index 9c0b353..8605be1 100644 --- a/examples/server_calling_server.rs +++ b/examples/server_calling_server.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate env_logger; diff --git a/examples/sync_server_calling_server.rs b/examples/sync_server_calling_server.rs index 8e39476..2c7f41b 100644 --- a/examples/sync_server_calling_server.rs +++ b/examples/sync_server_calling_server.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] extern crate env_logger; diff --git a/examples/throughput.rs b/examples/throughput.rs index 823041d..5d9eead 100644 --- a/examples/throughput.rs +++ b/examples/throughput.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] #[macro_use] diff --git a/examples/two_clients.rs b/examples/two_clients.rs index 3c5b941..039fa4a 100644 --- a/examples/two_clients.rs +++ b/examples/two_clients.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. -#![feature(plugin)] +#![feature(plugin, use_extern_macros)] #![plugin(tarpc_plugins)] #[macro_use] diff --git a/src/lib.rs b/src/lib.rs index a3d324c..2169965 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ //! Example usage: //! //! ``` -//! #![feature(plugin)] +//! #![feature(plugin, use_extern_macros)] //! #![plugin(tarpc_plugins)] //! //! #[macro_use] @@ -71,7 +71,7 @@ //! Example usage with TLS: //! //! ```no-run -//! #![feature(plugin)] +//! #![feature(plugin, use_extern_macros)] //! #![plugin(tarpc_plugins)] //! //! #[macro_use] @@ -116,7 +116,7 @@ #![deny(missing_docs, missing_debug_implementations)] #![feature(never_type)] -#![cfg_attr(test, feature(plugin))] +#![cfg_attr(test, feature(plugin, use_extern_macros))] #![cfg_attr(test, plugin(tarpc_plugins))] extern crate byteorder; @@ -129,8 +129,6 @@ extern crate lazy_static; extern crate log; extern crate net2; extern crate num_cpus; -#[macro_use] -extern crate serde_derive; extern crate thread_pool; extern crate tokio_io; @@ -142,6 +140,9 @@ pub extern crate futures; #[doc(hidden)] pub extern crate serde; #[doc(hidden)] +#[macro_use] +pub extern crate serde_derive; +#[doc(hidden)] pub extern crate tokio_core; #[doc(hidden)] pub extern crate tokio_proto; diff --git a/src/macros.rs b/src/macros.rs index 66eb82f..726c85b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -9,160 +9,12 @@ macro_rules! as_item { ($i:item) => {$i}; } -#[doc(hidden)] -#[macro_export] -macro_rules! impl_serialize { - ($impler:ident, { $($lifetime:tt)* }, $(@($name:ident $n:expr))* -- #($n_:expr) ) => { - as_item! { - impl$($lifetime)* $crate::serde::Serialize for $impler$($lifetime)* { - fn serialize(&self, impl_serialize_serializer__: S) - -> ::std::result::Result - where S: $crate::serde::Serializer - { - match *self { - $( - $impler::$name(ref impl_serialize_field__) => - $crate::serde::Serializer::serialize_newtype_variant( - impl_serialize_serializer__, - stringify!($impler), - $n, - stringify!($name), - impl_serialize_field__, - ) - ),* - } - } - } - } - }; - // All args are wrapped in a tuple so we can use the newtype variant for each one. - ($impler:ident, - { $($lifetime:tt)* }, - $(@$finished:tt)* - -- #($n:expr) $name:ident($field:ty) $($req:tt)*) => - ( - impl_serialize!($impler, - { $($lifetime)* }, - $(@$finished)* @($name $n) - -- #($n + 1) $($req)*); - ); - // Entry - ($impler:ident, - { $($lifetime:tt)* }, - $($started:tt)*) => (impl_serialize!($impler, { $($lifetime)* }, -- #(0) $($started)*);); -} - -#[doc(hidden)] -#[macro_export] -macro_rules! impl_deserialize { - ($impler:ident, $(@($name:ident $n:expr))* -- #($n_:expr) ) => ( - impl<'d> $crate::serde::Deserialize<'d> for $impler { - #[allow(non_camel_case_types)] - fn deserialize( - impl_deserialize_deserializer__: impl_deserialize_D__) - -> ::std::result::Result<$impler, impl_deserialize_D__::Error> - where impl_deserialize_D__: $crate::serde::Deserializer<'d> - { - #[allow(non_camel_case_types, unused)] - enum impl_deserialize_Field__ { - $($name),* - } - - impl<'d> $crate::serde::Deserialize<'d> for impl_deserialize_Field__ { - fn deserialize(impl_deserialize_deserializer__: D) - -> ::std::result::Result - where D: $crate::serde::Deserializer<'d> - { - struct impl_deserialize_FieldVisitor__; - impl<'d> $crate::serde::de::Visitor<'d> - for impl_deserialize_FieldVisitor__ - { - type Value = impl_deserialize_Field__; - - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) - -> ::std::fmt::Result - { - formatter.write_str("an unsigned integer") - } - - fn visit_u64(self, impl_deserialize_value__: u64) - -> ::std::result::Result - where E: $crate::serde::de::Error, - { - if impl_deserialize_value__ == 0 { - return ::std::result::Result::Err( - $crate::serde::de::Error::custom( - "Variant 0 is a sentinel value and should not \ - be serialized!")); - } - - $( - if impl_deserialize_value__ == $n { - return ::std::result::Result::Ok( - impl_deserialize_Field__::$name); - } - )* - ::std::result::Result::Err( - $crate::serde::de::Error::custom( - format!("No variants have a value of {}!", - impl_deserialize_value__)) - ) - } - } - impl_deserialize_deserializer__.deserialize_identifier( - impl_deserialize_FieldVisitor__) - } - } - - struct Visitor; - impl<'d> $crate::serde::de::Visitor<'d> for Visitor { - type Value = $impler; - - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) - -> ::std::fmt::Result - { - formatter.write_str("an enum variant") - } - - fn visit_enum(self, data__: V) - -> ::std::result::Result - where V: $crate::serde::de::EnumAccess<'d> - { - use $crate::serde::de::VariantAccess; - match data__.variant()? { - $( - (impl_deserialize_Field__::$name, variant) => { - ::std::result::Result::Ok( - $impler::$name(variant.newtype_variant()?)) - } - ),* - } - } - } - const TARPC_VARIANTS__: &'static [&'static str] = &[ - $( - stringify!($name) - ),* - ]; - impl_deserialize_deserializer__.deserialize_enum( - stringify!($impler), TARPC_VARIANTS__, Visitor) - } - } - ); - // All args are wrapped in a tuple so we can use the newtype variant for each one. - ($impler:ident, $(@$finished:tt)* -- #($n:expr) $name:ident($field:ty) $($req:tt)*) => ( - impl_deserialize!($impler, $(@$finished)* @($name $n) -- #($n + 1) $($req)*); - ); - // Entry - ($impler:ident, $($started:tt)*) => (impl_deserialize!($impler, -- #(0) $($started)*);); -} - /// The main macro that creates RPC services. /// /// Rpc methods are specified, mirroring trait syntax: /// /// ``` -/// # #![feature(plugin)] +/// # #![feature(plugin, use_extern_macros)] /// # #![plugin(tarpc_plugins)] /// # #[macro_use] extern crate tarpc; /// # fn main() {} @@ -292,18 +144,17 @@ macro_rules! service { #[doc(hidden)] #[allow(non_camel_case_types, unused)] + #[derive($crate::serde_derive::Serialize, $crate::serde_derive::Deserialize)] pub enum Request__ { NotIrrefutable(()), $( - $fn_name(( $($in_,)* )) + $fn_name{ $($arg: $in_,)* } ),* } - impl_deserialize!(Request__, NotIrrefutable(()) $($fn_name(($($in_),*)))*); - impl_serialize!(Request__, {}, NotIrrefutable(()) $($fn_name(($($in_),*)))*); - #[doc(hidden)] #[allow(non_camel_case_types, unused)] + #[derive($crate::serde_derive::Serialize, $crate::serde_derive::Deserialize)] pub enum Response__ { NotIrrefutable(()), $( @@ -311,12 +162,9 @@ macro_rules! service { ),* } - impl_deserialize!(Response__, NotIrrefutable(()) $($fn_name($out))*); - impl_serialize!(Response__, {}, NotIrrefutable(()) $($fn_name($out))*); - #[doc(hidden)] #[allow(non_camel_case_types, unused)] - #[derive(Debug)] + #[derive(Debug, $crate::serde_derive::Deserialize, $crate::serde_derive::Serialize)] pub enum Error__ { NotIrrefutable(()), $( @@ -324,9 +172,6 @@ macro_rules! service { ),* } - impl_deserialize!(Error__, NotIrrefutable(()) $($fn_name($error))*); - impl_serialize!(Error__, {}, NotIrrefutable(()) $($fn_name($error))*); - /// Defines the `Future` RPC service. Implementors must be `Clone` and `'static`, /// as required by `tokio_proto::NewService`. This is required so that the service can be used /// to respond to multiple requests concurrently. @@ -413,7 +258,7 @@ macro_rules! service { match request__ { Request__::NotIrrefutable(()) => unreachable!(), $( - Request__::$fn_name(( $($arg,)* )) => { + Request__::$fn_name{ $($arg,)* } => { fn wrap__(response__: ::std::result::Result<$out, $error>) -> ResponseFuture__ { @@ -583,7 +428,7 @@ macro_rules! service { -> ::std::result::Result<$out, $crate::Error<$error>> { tarpc_service_then__!($out, $error, $fn_name); - let resp__ = self.inner.call(Request__::$fn_name(($($arg,)*))); + let resp__ = self.inner.call(Request__::$fn_name { $($arg,)* }); tarpc_service_then__(resp__) } )* @@ -648,7 +493,7 @@ macro_rules! service { -> ::std::result::Result<$out, $crate::Error<$error>>> { tarpc_service_then__!($out, $error, $fn_name); - let request__ = Request__::$fn_name(($($arg,)*)); + let request__ = Request__::$fn_name { $($arg,)* }; let future__ = $crate::tokio_service::Service::call(&self.0, request__); return $crate::futures::Future::then(future__, tarpc_service_then__); }