mirror of
https://github.com/OMGeeky/tarpc.git
synced 2026-02-23 15:49:54 +01:00
Feature rollup (#129)
* Create a directory for the `future::server` module, which has become quite large. server.rs => server/mod.rs. Server submodules for shutdown and connection logic are added. * Add fn thread_pool(...) to sync::server::Options * Configure idle threads to expire after one minute * Add tarpc::util::lazy for lazily executing functions. Similar to `futures::lazy` but useful in different circumstances. Specifically, `futures::lazy` typically requires a closure, whereas `util::lazy` kind of deconstructs a closure into its function and args. * Remove some unstable features, and `cfg(plugin)` only in tests. Features `unboxed_closures` and `fn_traits` are removed by replacing manual Fn impls with Stream impls. This actually leads to slightly more performant code, as well, because some `Rc`s could be removed. * Fix tokio deprecation warnings. Update to use tokio-io in lieu of deprecated tokio-core items. impl AsyncRead's optional `unsafe fn prepare_uninitialized_buffer` for huge perf wins * Add debug impls to all public items and add `deny(missing_debug_implementations)` to the crate. * Bump tokio core version.
This commit is contained in:
411
src/macros.rs
411
src/macros.rs
@@ -122,12 +122,12 @@ macro_rules! impl_deserialize {
|
||||
formatter.write_str("an enum variant")
|
||||
}
|
||||
|
||||
fn visit_enum<V>(self, tarpc_enum_visitor__: V)
|
||||
fn visit_enum<V>(self, visitor__: V)
|
||||
-> ::std::result::Result<Self::Value, V::Error>
|
||||
where V: $crate::serde::de::EnumVisitor
|
||||
{
|
||||
use $crate::serde::de::VariantVisitor;
|
||||
match tarpc_enum_visitor__.visit_variant()? {
|
||||
match visitor__.visit_variant()? {
|
||||
$(
|
||||
(impl_deserialize_Field__::$name, variant) => {
|
||||
::std::result::Result::Ok(
|
||||
@@ -290,40 +290,40 @@ macro_rules! service {
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_camel_case_types, unused)]
|
||||
pub enum tarpc_service_Request__ {
|
||||
pub enum Request__ {
|
||||
NotIrrefutable(()),
|
||||
$(
|
||||
$fn_name(( $($in_,)* ))
|
||||
),*
|
||||
}
|
||||
|
||||
impl_deserialize!(tarpc_service_Request__, NotIrrefutable(()) $($fn_name(($($in_),*)))*);
|
||||
impl_serialize!(tarpc_service_Request__, {}, NotIrrefutable(()) $($fn_name(($($in_),*)))*);
|
||||
impl_deserialize!(Request__, NotIrrefutable(()) $($fn_name(($($in_),*)))*);
|
||||
impl_serialize!(Request__, {}, NotIrrefutable(()) $($fn_name(($($in_),*)))*);
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_camel_case_types, unused)]
|
||||
pub enum tarpc_service_Response__ {
|
||||
pub enum Response__ {
|
||||
NotIrrefutable(()),
|
||||
$(
|
||||
$fn_name($out)
|
||||
),*
|
||||
}
|
||||
|
||||
impl_deserialize!(tarpc_service_Response__, NotIrrefutable(()) $($fn_name($out))*);
|
||||
impl_serialize!(tarpc_service_Response__, {}, NotIrrefutable(()) $($fn_name($out))*);
|
||||
impl_deserialize!(Response__, NotIrrefutable(()) $($fn_name($out))*);
|
||||
impl_serialize!(Response__, {}, NotIrrefutable(()) $($fn_name($out))*);
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_camel_case_types, unused)]
|
||||
#[derive(Debug)]
|
||||
pub enum tarpc_service_Error__ {
|
||||
pub enum Error__ {
|
||||
NotIrrefutable(()),
|
||||
$(
|
||||
$fn_name($error)
|
||||
),*
|
||||
}
|
||||
|
||||
impl_deserialize!(tarpc_service_Error__, NotIrrefutable(()) $($fn_name($error))*);
|
||||
impl_serialize!(tarpc_service_Error__, {}, NotIrrefutable(()) $($fn_name($error))*);
|
||||
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
|
||||
@@ -333,7 +333,6 @@ macro_rules! service {
|
||||
'static
|
||||
{
|
||||
$(
|
||||
|
||||
snake_to_camel! {
|
||||
/// The type of future returned by `{}`.
|
||||
type $fn_name: $crate::futures::IntoFuture<Item=$out, Error=$error>;
|
||||
@@ -346,50 +345,42 @@ macro_rules! service {
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone)]
|
||||
struct tarpc_service_AsyncServer__<S>(S);
|
||||
struct TarpcNewService<S>(S);
|
||||
|
||||
impl<S> ::std::fmt::Debug for tarpc_service_AsyncServer__<S> {
|
||||
impl<S> ::std::fmt::Debug for TarpcNewService<S> {
|
||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(fmt, "tarpc_service_AsyncServer__ {{ .. }}")
|
||||
fmt.debug_struct("TarpcNewService").finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type tarpc_service_Future__ =
|
||||
$crate::futures::Finished<$crate::future::server::Response<tarpc_service_Response__,
|
||||
tarpc_service_Error__>,
|
||||
type ResponseFuture__ =
|
||||
$crate::futures::Finished<$crate::future::server::Response<Response__,
|
||||
Error__>,
|
||||
::std::io::Error>;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
enum tarpc_service_FutureReply__<tarpc_service_S__: FutureService> {
|
||||
DeserializeError(tarpc_service_Future__),
|
||||
enum FutureReply__<S__: FutureService> {
|
||||
DeserializeError(ResponseFuture__),
|
||||
$($fn_name(
|
||||
$crate::futures::Then<
|
||||
<ty_snake_to_camel!(tarpc_service_S__::$fn_name)
|
||||
as $crate::futures::IntoFuture>::Future,
|
||||
tarpc_service_Future__,
|
||||
fn(::std::result::Result<$out, $error>)
|
||||
-> tarpc_service_Future__>)),*
|
||||
<ty_snake_to_camel!(S__::$fn_name) as $crate::futures::IntoFuture>::Future,
|
||||
ResponseFuture__,
|
||||
fn(::std::result::Result<$out, $error>) -> ResponseFuture__>)),*
|
||||
}
|
||||
|
||||
impl<S: FutureService> $crate::futures::Future for tarpc_service_FutureReply__<S> {
|
||||
type Item = $crate::future::server::Response<tarpc_service_Response__,
|
||||
tarpc_service_Error__>;
|
||||
|
||||
impl<S: FutureService> $crate::futures::Future for FutureReply__<S> {
|
||||
type Item = $crate::future::server::Response<Response__, Error__>;
|
||||
type Error = ::std::io::Error;
|
||||
|
||||
fn poll(&mut self) -> $crate::futures::Poll<Self::Item, Self::Error> {
|
||||
match *self {
|
||||
tarpc_service_FutureReply__::DeserializeError(
|
||||
ref mut tarpc_service_future__) =>
|
||||
{
|
||||
$crate::futures::Future::poll(tarpc_service_future__)
|
||||
FutureReply__::DeserializeError(ref mut future__) => {
|
||||
$crate::futures::Future::poll(future__)
|
||||
}
|
||||
$(
|
||||
tarpc_service_FutureReply__::$fn_name(
|
||||
ref mut tarpc_service_future__) =>
|
||||
{
|
||||
$crate::futures::Future::poll(tarpc_service_future__)
|
||||
FutureReply__::$fn_name(ref mut future__) => {
|
||||
$crate::futures::Future::poll(future__)
|
||||
}
|
||||
),*
|
||||
}
|
||||
@@ -398,53 +389,45 @@ macro_rules! service {
|
||||
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
impl<tarpc_service_S__> $crate::tokio_service::Service
|
||||
for tarpc_service_AsyncServer__<tarpc_service_S__>
|
||||
where tarpc_service_S__: FutureService
|
||||
impl<S__> $crate::tokio_service::Service for TarpcNewService<S__>
|
||||
where S__: FutureService
|
||||
{
|
||||
type Request = ::std::result::Result<tarpc_service_Request__,
|
||||
$crate::bincode::Error>;
|
||||
type Response = $crate::future::server::Response<tarpc_service_Response__,
|
||||
tarpc_service_Error__>;
|
||||
type Request = ::std::result::Result<Request__, $crate::bincode::Error>;
|
||||
type Response = $crate::future::server::Response<Response__, Error__>;
|
||||
type Error = ::std::io::Error;
|
||||
type Future = tarpc_service_FutureReply__<tarpc_service_S__>;
|
||||
type Future = FutureReply__<S__>;
|
||||
|
||||
fn call(&self, tarpc_service_request__: Self::Request) -> Self::Future {
|
||||
let tarpc_service_request__ = match tarpc_service_request__ {
|
||||
Ok(tarpc_service_request__) => tarpc_service_request__,
|
||||
Err(tarpc_service_deserialize_err__) => {
|
||||
return tarpc_service_FutureReply__::DeserializeError(
|
||||
fn call(&self, request__: Self::Request) -> Self::Future {
|
||||
let request__ = match request__ {
|
||||
Ok(request__) => request__,
|
||||
Err(err__) => {
|
||||
return FutureReply__::DeserializeError(
|
||||
$crate::futures::finished(
|
||||
::std::result::Result::Err(
|
||||
$crate::WireError::RequestDeserialize(
|
||||
::std::string::ToString::to_string(
|
||||
&tarpc_service_deserialize_err__)))));
|
||||
::std::string::ToString::to_string(&err__)))));
|
||||
}
|
||||
};
|
||||
match tarpc_service_request__ {
|
||||
tarpc_service_Request__::NotIrrefutable(()) => unreachable!(),
|
||||
match request__ {
|
||||
Request__::NotIrrefutable(()) => unreachable!(),
|
||||
$(
|
||||
tarpc_service_Request__::$fn_name(( $($arg,)* )) => {
|
||||
fn tarpc_service_wrap__(
|
||||
tarpc_service_response__:
|
||||
::std::result::Result<$out, $error>)
|
||||
-> tarpc_service_Future__
|
||||
Request__::$fn_name(( $($arg,)* )) => {
|
||||
fn wrap__(response__: ::std::result::Result<$out, $error>)
|
||||
-> ResponseFuture__
|
||||
{
|
||||
$crate::futures::finished(
|
||||
tarpc_service_response__
|
||||
.map(tarpc_service_Response__::$fn_name)
|
||||
.map_err(|tarpc_service_error__| {
|
||||
$crate::WireError::App(
|
||||
tarpc_service_Error__::$fn_name(
|
||||
tarpc_service_error__))
|
||||
response__
|
||||
.map(Response__::$fn_name)
|
||||
.map_err(|err__| {
|
||||
$crate::WireError::App(Error__::$fn_name(err__))
|
||||
})
|
||||
)
|
||||
}
|
||||
return tarpc_service_FutureReply__::$fn_name(
|
||||
return FutureReply__::$fn_name(
|
||||
$crate::futures::Future::then(
|
||||
$crate::futures::IntoFuture::into_future(
|
||||
FutureService::$fn_name(&self.0, $($arg),*)),
|
||||
tarpc_service_wrap__));
|
||||
wrap__));
|
||||
}
|
||||
)*
|
||||
}
|
||||
@@ -452,9 +435,9 @@ macro_rules! service {
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
impl<tarpc_service_S__> $crate::tokio_service::NewService
|
||||
for tarpc_service_AsyncServer__<tarpc_service_S__>
|
||||
where tarpc_service_S__: FutureService
|
||||
impl<S__> $crate::tokio_service::NewService
|
||||
for TarpcNewService<S__>
|
||||
where S__: FutureService
|
||||
{
|
||||
type Request = <Self as $crate::tokio_service::Service>::Request;
|
||||
type Response = <Self as $crate::tokio_service::Service>::Response;
|
||||
@@ -471,10 +454,10 @@ macro_rules! service {
|
||||
pub struct Listen<S>
|
||||
where S: FutureService,
|
||||
{
|
||||
inner: $crate::future::server::Listen<tarpc_service_AsyncServer__<S>,
|
||||
tarpc_service_Request__,
|
||||
tarpc_service_Response__,
|
||||
tarpc_service_Error__>,
|
||||
inner: $crate::future::server::Listen<TarpcNewService<S>,
|
||||
Request__,
|
||||
Response__,
|
||||
Error__>,
|
||||
}
|
||||
|
||||
impl<S> $crate::futures::Future for Listen<S>
|
||||
@@ -502,10 +485,10 @@ macro_rules! service {
|
||||
options: $crate::future::server::Options)
|
||||
-> ::std::io::Result<($crate::future::server::Handle, Listen<Self>)>
|
||||
{
|
||||
$crate::future::server::Handle::listen(tarpc_service_AsyncServer__(self),
|
||||
addr,
|
||||
handle,
|
||||
options)
|
||||
$crate::future::server::listen(TarpcNewService(self),
|
||||
addr,
|
||||
handle,
|
||||
options)
|
||||
.map(|(handle, inner)| (handle, Listen { inner }))
|
||||
}
|
||||
}
|
||||
@@ -534,59 +517,36 @@ macro_rules! service {
|
||||
-> ::std::io::Result<$crate::sync::server::Handle>
|
||||
where A: ::std::net::ToSocketAddrs
|
||||
{
|
||||
let tarpc_service__ = tarpc_service_AsyncServer__(SyncServer__ {
|
||||
service: self,
|
||||
});
|
||||
|
||||
let tarpc_service_addr__ =
|
||||
$crate::util::FirstSocketAddr::try_first_socket_addr(&addr)?;
|
||||
|
||||
return $crate::sync::server::Handle::listen(tarpc_service__,
|
||||
tarpc_service_addr__,
|
||||
options);
|
||||
|
||||
#[derive(Clone)]
|
||||
struct SyncServer__<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
impl<tarpc_service_S__> FutureService for SyncServer__<tarpc_service_S__>
|
||||
where tarpc_service_S__: SyncService
|
||||
{
|
||||
struct BlockingFutureService<S>(S);
|
||||
impl<S: SyncService> FutureService for BlockingFutureService<S> {
|
||||
$(
|
||||
impl_snake_to_camel! {
|
||||
type $fn_name =
|
||||
$crate::futures::Flatten<
|
||||
$crate::futures::MapErr<
|
||||
$crate::futures::Oneshot<
|
||||
$crate::futures::Done<$out, $error>>,
|
||||
fn($crate::futures::Canceled) -> $error>>;
|
||||
$crate::util::Lazy<
|
||||
fn((S, $($in_),*)) -> ::std::result::Result<$out, $error>,
|
||||
(S, $($in_),*),
|
||||
::std::result::Result<$out, $error>>;
|
||||
}
|
||||
fn $fn_name(&self, $($arg:$in_),*) -> ty_snake_to_camel!(Self::$fn_name) {
|
||||
fn unimplemented(_: $crate::futures::Canceled) -> $error {
|
||||
// TODO(tikue): what do do if SyncService panics?
|
||||
unimplemented!()
|
||||
|
||||
$(#[$attr])*
|
||||
fn $fn_name(&self, $($arg:$in_),*)
|
||||
-> $crate::util::Lazy<
|
||||
fn((S, $($in_),*)) -> ::std::result::Result<$out, $error>,
|
||||
(S, $($in_),*),
|
||||
::std::result::Result<$out, $error>> {
|
||||
fn execute<S: SyncService>((s, $($arg),*): (S, $($in_),*))
|
||||
-> ::std::result::Result<$out, $error> {
|
||||
SyncService::$fn_name(&s, $($arg),*)
|
||||
}
|
||||
let (tarpc_service_complete__, tarpc_service_promise__) =
|
||||
$crate::futures::oneshot();
|
||||
let tarpc_service__ = self.clone();
|
||||
const UNIMPLEMENTED: fn($crate::futures::Canceled) -> $error =
|
||||
unimplemented;
|
||||
::std::thread::spawn(move || {
|
||||
let tarpc_service_reply__ = SyncService::$fn_name(
|
||||
&tarpc_service__.service, $($arg),*);
|
||||
tarpc_service_complete__.complete(
|
||||
$crate::futures::IntoFuture::into_future(
|
||||
tarpc_service_reply__));
|
||||
});
|
||||
let tarpc_service_promise__ =
|
||||
$crate::futures::Future::map_err(
|
||||
tarpc_service_promise__, UNIMPLEMENTED);
|
||||
$crate::futures::Future::flatten(tarpc_service_promise__)
|
||||
$crate::util::lazy(execute, (self.0.clone(), $($arg),*))
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
let tarpc_service__ = TarpcNewService(BlockingFutureService(self));
|
||||
let addr__ = $crate::util::FirstSocketAddr::try_first_socket_addr(&addr)?;
|
||||
return $crate::sync::server::listen(tarpc_service__, addr__, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +557,7 @@ macro_rules! service {
|
||||
#[allow(unused)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SyncClient {
|
||||
inner: tarpc_service_SyncClient__,
|
||||
inner: SyncClient__,
|
||||
}
|
||||
|
||||
impl $crate::sync::client::ClientExt for SyncClient {
|
||||
@@ -605,8 +565,8 @@ macro_rules! service {
|
||||
-> ::std::io::Result<Self>
|
||||
where A: ::std::net::ToSocketAddrs,
|
||||
{
|
||||
let client_ = <tarpc_service_SyncClient__
|
||||
as $crate::sync::client::ClientExt>::connect(addr_, options_)?;
|
||||
let client_ =
|
||||
<SyncClient__ as $crate::sync::client::ClientExt>::connect(addr_, options_)?;
|
||||
::std::result::Result::Ok(SyncClient {
|
||||
inner: client_,
|
||||
})
|
||||
@@ -620,71 +580,26 @@ macro_rules! service {
|
||||
pub fn $fn_name(&self, $($arg: $in_),*)
|
||||
-> ::std::result::Result<$out, $crate::Error<$error>>
|
||||
{
|
||||
return then__(self.inner.call(tarpc_service_Request__::$fn_name(($($arg,)*))));
|
||||
|
||||
// TODO: this code is duplicated in both FutureClient and SyncClient.
|
||||
fn then__(tarpc_service_msg__:
|
||||
::std::result::Result<tarpc_service_Response__,
|
||||
$crate::Error<tarpc_service_Error__>>)
|
||||
-> ::std::result::Result<$out, $crate::Error<$error>> {
|
||||
match tarpc_service_msg__ {
|
||||
::std::result::Result::Ok(tarpc_service_msg__) => {
|
||||
if let tarpc_service_Response__::$fn_name(tarpc_service_msg__) =
|
||||
tarpc_service_msg__
|
||||
{
|
||||
::std::result::Result::Ok(tarpc_service_msg__)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
::std::result::Result::Err(tarpc_service_err__) => {
|
||||
::std::result::Result::Err(match tarpc_service_err__ {
|
||||
$crate::Error::App(tarpc_service_err__) => {
|
||||
if let tarpc_service_Error__::$fn_name(
|
||||
tarpc_service_err__) = tarpc_service_err__
|
||||
{
|
||||
$crate::Error::App(tarpc_service_err__)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
$crate::Error::RequestDeserialize(tarpc_service_err__) => {
|
||||
$crate::Error::RequestDeserialize(tarpc_service_err__)
|
||||
}
|
||||
$crate::Error::ResponseDeserialize(tarpc_service_err__) => {
|
||||
$crate::Error::ResponseDeserialize(tarpc_service_err__)
|
||||
}
|
||||
$crate::Error::Io(tarpc_service_error__) => {
|
||||
$crate::Error::Io(tarpc_service_error__)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
tarpc_service_then__!($out, $error, $fn_name);
|
||||
let resp__ = self.inner.call(Request__::$fn_name(($($arg,)*)));
|
||||
tarpc_service_then__(resp__)
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type tarpc_service_FutureClient__ =
|
||||
$crate::future::client::Client<tarpc_service_Request__,
|
||||
tarpc_service_Response__,
|
||||
tarpc_service_Error__>;
|
||||
type FutureClient__ = $crate::future::client::Client<Request__, Response__, Error__>;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type tarpc_service_SyncClient__ =
|
||||
$crate::sync::client::Client<tarpc_service_Request__,
|
||||
tarpc_service_Response__,
|
||||
tarpc_service_Error__>;
|
||||
type SyncClient__ = $crate::sync::client::Client<Request__, Response__, Error__>;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// A future representing a client connecting to a server.
|
||||
pub struct Connect<T> {
|
||||
inner: $crate::futures::Map<$crate::future::client::ConnectFuture<
|
||||
tarpc_service_Request__,
|
||||
tarpc_service_Response__,
|
||||
tarpc_service_Error__>,
|
||||
fn(tarpc_service_FutureClient__) -> T>,
|
||||
inner:
|
||||
$crate::futures::Map<
|
||||
$crate::future::client::ConnectFuture< Request__, Response__, Error__>,
|
||||
fn(FutureClient__) -> T>,
|
||||
}
|
||||
|
||||
impl<T> $crate::futures::Future for Connect<T> {
|
||||
@@ -699,18 +614,18 @@ macro_rules! service {
|
||||
#[allow(unused)]
|
||||
#[derive(Clone, Debug)]
|
||||
/// The client stub that makes RPC calls to the server. Exposes a Future interface.
|
||||
pub struct FutureClient(tarpc_service_FutureClient__);
|
||||
pub struct FutureClient(FutureClient__);
|
||||
|
||||
impl<'a> $crate::future::client::ClientExt for FutureClient {
|
||||
type ConnectFut = Connect<Self>;
|
||||
|
||||
fn connect(tarpc_service_addr__: ::std::net::SocketAddr,
|
||||
tarpc_service_options__: $crate::future::client::Options)
|
||||
fn connect(addr__: ::std::net::SocketAddr,
|
||||
options__: $crate::future::client::Options)
|
||||
-> Self::ConnectFut
|
||||
{
|
||||
let client = <tarpc_service_FutureClient__
|
||||
as $crate::future::client::ClientExt>::connect(tarpc_service_addr__,
|
||||
tarpc_service_options__);
|
||||
let client =
|
||||
<FutureClient__ as $crate::future::client::ClientExt>::connect(addr__,
|
||||
options__);
|
||||
|
||||
Connect {
|
||||
inner: $crate::futures::Future::map(client, FutureClient)
|
||||
@@ -724,61 +639,67 @@ macro_rules! service {
|
||||
$(#[$attr])*
|
||||
pub fn $fn_name(&self, $($arg: $in_),*)
|
||||
-> $crate::futures::future::Then<
|
||||
<tarpc_service_FutureClient__ as $crate::tokio_service::Service>::Future,
|
||||
<FutureClient__ as $crate::tokio_service::Service>::Future,
|
||||
::std::result::Result<$out, $crate::Error<$error>>,
|
||||
fn(::std::result::Result<tarpc_service_Response__,
|
||||
$crate::Error<tarpc_service_Error__>>)
|
||||
fn(::std::result::Result<Response__,
|
||||
$crate::Error<Error__>>)
|
||||
-> ::std::result::Result<$out, $crate::Error<$error>>> {
|
||||
tarpc_service_then__!($out, $error, $fn_name);
|
||||
|
||||
let tarpc_service_req__ = tarpc_service_Request__::$fn_name(($($arg,)*));
|
||||
let tarpc_service_fut__ =
|
||||
$crate::tokio_service::Service::call(&self.0, tarpc_service_req__);
|
||||
return $crate::futures::Future::then(tarpc_service_fut__, then__);
|
||||
|
||||
fn then__(tarpc_service_msg__:
|
||||
::std::result::Result<tarpc_service_Response__,
|
||||
$crate::Error<tarpc_service_Error__>>)
|
||||
-> ::std::result::Result<$out, $crate::Error<$error>> {
|
||||
match tarpc_service_msg__ {
|
||||
::std::result::Result::Ok(tarpc_service_msg__) => {
|
||||
if let tarpc_service_Response__::$fn_name(tarpc_service_msg__) =
|
||||
tarpc_service_msg__
|
||||
{
|
||||
::std::result::Result::Ok(tarpc_service_msg__)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
::std::result::Result::Err(tarpc_service_err__) => {
|
||||
::std::result::Result::Err(match tarpc_service_err__ {
|
||||
$crate::Error::App(tarpc_service_err__) => {
|
||||
if let tarpc_service_Error__::$fn_name(
|
||||
tarpc_service_err__) = tarpc_service_err__
|
||||
{
|
||||
$crate::Error::App(tarpc_service_err__)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
$crate::Error::RequestDeserialize(tarpc_service_err__) => {
|
||||
$crate::Error::RequestDeserialize(tarpc_service_err__)
|
||||
}
|
||||
$crate::Error::ResponseDeserialize(tarpc_service_err__) => {
|
||||
$crate::Error::ResponseDeserialize(tarpc_service_err__)
|
||||
}
|
||||
$crate::Error::Io(tarpc_service_error__) => {
|
||||
$crate::Error::Io(tarpc_service_error__)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
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__);
|
||||
}
|
||||
)*
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! tarpc_service_then__ {
|
||||
($out:ty, $error:ty, $fn_name:ident) => {
|
||||
fn tarpc_service_then__(msg__:
|
||||
::std::result::Result<Response__,
|
||||
$crate::Error<Error__>>)
|
||||
-> ::std::result::Result<$out, $crate::Error<$error>> {
|
||||
match msg__ {
|
||||
::std::result::Result::Ok(msg__) => {
|
||||
if let Response__::$fn_name(msg__) =
|
||||
msg__
|
||||
{
|
||||
::std::result::Result::Ok(msg__)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
::std::result::Result::Err(err__) => {
|
||||
::std::result::Result::Err(match err__ {
|
||||
$crate::Error::App(err__) => {
|
||||
if let Error__::$fn_name(
|
||||
err__) = err__
|
||||
{
|
||||
$crate::Error::App(err__)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
$crate::Error::RequestDeserialize(err__) => {
|
||||
$crate::Error::RequestDeserialize(err__)
|
||||
}
|
||||
$crate::Error::ResponseDeserialize(err__) => {
|
||||
$crate::Error::ResponseDeserialize(err__)
|
||||
}
|
||||
$crate::Error::Io(err__) => {
|
||||
$crate::Error::Io(err__)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// allow dead code; we're just testing that the macro expansion compiles
|
||||
#[allow(dead_code)]
|
||||
#[cfg(test)]
|
||||
@@ -1101,8 +1022,8 @@ mod functional_test {
|
||||
let _ = env_logger::init();
|
||||
let (addr, client, shutdown) = unwrap!(start_server_with_sync_client::<SyncClient,
|
||||
Server>(Server));
|
||||
assert_eq!(3, client.add(1, 2).unwrap());
|
||||
assert_eq!("Hey, Tim.", client.hey("Tim".to_string()).unwrap());
|
||||
assert_eq!(3, unwrap!(client.add(1, 2)));
|
||||
assert_eq!("Hey, Tim.", unwrap!(client.hey("Tim".to_string())));
|
||||
|
||||
info!("Dropping client.");
|
||||
drop(client);
|
||||
@@ -1110,23 +1031,23 @@ mod functional_test {
|
||||
let (tx2, rx2) = ::std::sync::mpsc::channel();
|
||||
let shutdown2 = shutdown.clone();
|
||||
::std::thread::spawn(move || {
|
||||
let client = get_sync_client::<SyncClient>(addr).unwrap();
|
||||
tx.send(()).unwrap();
|
||||
let add = client.add(3, 2).unwrap();
|
||||
let client = unwrap!(get_sync_client::<SyncClient>(addr));
|
||||
let add = unwrap!(client.add(3, 2));
|
||||
unwrap!(tx.send(()));
|
||||
drop(client);
|
||||
// Make sure 2 shutdowns are concurrent safe.
|
||||
shutdown2.shutdown().wait().unwrap();
|
||||
tx2.send(add).unwrap();
|
||||
unwrap!(shutdown2.shutdown().wait());
|
||||
unwrap!(tx2.send(add));
|
||||
});
|
||||
rx.recv().unwrap();
|
||||
unwrap!(rx.recv());
|
||||
let mut shutdown1 = shutdown.shutdown();
|
||||
shutdown.shutdown().wait().unwrap();
|
||||
unwrap!(shutdown.shutdown().wait());
|
||||
// Assert shutdown2 blocks until shutdown is complete.
|
||||
if let Async::NotReady = shutdown1.poll().unwrap() {
|
||||
if let Async::NotReady = unwrap!(shutdown1.poll()) {
|
||||
panic!("Shutdown should have completed");
|
||||
}
|
||||
// Existing clients are served
|
||||
assert_eq!(5, rx2.recv().unwrap());
|
||||
assert_eq!(5, unwrap!(rx2.recv()));
|
||||
|
||||
let e = get_sync_client::<SyncClient>(addr).err().unwrap();
|
||||
debug!("(Success) shutdown caused client err: {}", e);
|
||||
@@ -1162,10 +1083,10 @@ mod functional_test {
|
||||
}
|
||||
|
||||
mod bad_serialize {
|
||||
use sync::{client, server};
|
||||
use sync::client::ClientExt;
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::ser::SerializeSeq;
|
||||
use sync::{client, server};
|
||||
use sync::client::ClientExt;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Bad;
|
||||
|
||||
Reference in New Issue
Block a user