#[macro_export]
macro_rules! rpc_service {
(
Request = $request:ident;
Response = $response:ident;
Service = $service:ident;
CreateDispatch = $create_dispatch:tt;
$($m_pattern:ident $m_name:ident = $m_input:ident, $m_update:tt -> $m_output:ident);+$(;)?
) => {
$crate::__request_enum! {
$service,
$request {
$($m_input,)*
$($m_update,)*
}
}
#[doc=concat!("Response messages for ", stringify!($service))]
#[allow(clippy::enum_variant_names)]
#[derive(::std::fmt::Debug, ::derive_more::From, ::derive_more::TryInto, ::serde::Serialize, ::serde::Deserialize)]
pub enum $response {
$($m_output($m_output),)*
}
$(
$crate::__rpc_message!($service, $m_pattern, $m_input, $m_update, $m_output);
)*
#[doc=concat!("RPC service ", stringify!($service))]
#[derive(::std::clone::Clone, ::std::fmt::Debug)]
pub struct $service;
impl $crate::Service for $service {
type Req = $request;
type Res = $response;
}
$crate::__derive_create_dispatch!(
$service,
$request,
$create_dispatch,
[ $($m_pattern $m_name = $m_input, $m_update -> $m_output);+ ]
);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __derive_create_dispatch {
(
$service:ident,
$request:ident,
_,
[ $($tt:tt)* ]
) => {};
(
$service:ident,
$request:ident,
$create_dispatch:ident,
[ $($m_pattern:ident $m_name:ident = $m_input:ident, $m_update:tt -> $m_output:ident);+ ]
) => {
#[doc = concat!("Create an RPC request dispatch function for ", stringify!($service), "\n\nSee the docs for [quic_rpc::rpc_service] for usage docs.")]
#[macro_export]
macro_rules! $create_dispatch {
($target:ident, $handler:ident) => {
pub async fn $handler<C: $crate::Listener<$service>>(
mut chan: $crate::server::RpcChannel<$service, C>,
msg: <$service as $crate::Service>::Req,
target: $target,
) -> Result<(), $crate::server::RpcServerError<C>> {
let res = match msg {
$(
$request::$m_input(msg) => { $crate::__rpc_invoke!($m_pattern, $m_name, $target, msg, chan, target) },
)*
_ => Err($crate::server::RpcServerError::<C>::UnexpectedStartMessage),
};
res?;
Ok(())
}
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __request_enum {
($service:ident, $enum_name:ident { $variant_name:ident $($tt:tt)* }) => {
$crate::__request_enum!(@ {[$service $enum_name] [$variant_name]} $($tt)*);
};
(@ {[$service:ident $enum_name:ident] [$($agg:ident)*]} $(,)? $(_$(,)?)* $variant_name:ident $($tt:tt)*) => {
$crate::__request_enum!(@ {[$service $enum_name] [$($agg)* $variant_name]} $($tt)*);
};
(@ {[$service:ident $enum_name:ident] [$($agg:ident)*]} $(,)? $variant_name:ident $($tt:tt)*) => {
$crate::__request_enum!(@ {[$service $enum_name] [$($agg)* $variant_name]} $($tt)*);
};
(@ {[$service:ident $enum_name:ident] [$($n:ident)*]} $(,)? $(_$(,)?)*) => {
#[doc=concat!("Request messages for ", stringify!($service))]
#[derive(::std::fmt::Debug, ::derive_more::From, ::derive_more::TryInto, ::serde::Serialize, ::serde::Deserialize)]
pub enum $enum_name {
$($n($n),)*
}
};
}
#[macro_export]
macro_rules! declare_rpc {
($service:ty, $m_input:ty, $m_output:ty) => {
impl $crate::message::RpcMsg<$service> for $m_input {
type Response = $m_output;
}
};
}
#[macro_export]
macro_rules! declare_server_streaming {
($service:ident, $m_input:ident, $m_output:ident) => {
impl $crate::message::Msg<$service> for $m_input {
type Pattern = $crate::message::ServerStreaming;
}
impl $crate::message::ServerStreamingMsg<$service> for $m_input {
type Response = $m_output;
}
};
}
#[macro_export]
macro_rules! declare_client_streaming {
($service:ident, $m_input:ident, $m_update:ident, $m_output:ident) => {
impl $crate::message::Msg<$service> for $m_input {
type Pattern = $crate::message::ClientStreaming;
}
impl $crate::message::ClientStreamingMsg<$service> for $m_input {
type Update = $m_update;
type Response = $m_output;
}
};
}
#[macro_export]
macro_rules! declare_bidi_streaming {
($service:ident, $m_input:ident, $m_update:ident, $m_output:ident) => {
impl $crate::message::Msg<$service> for $m_input {
type Pattern = $crate::message::BidiStreaming;
}
impl $crate::message::BidiStreamingMsg<$service> for $m_input {
type Update = $m_update;
type Response = $m_output;
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rpc_message {
($service:ident, Rpc, $m_input:ident, _, $m_output:ident) => {
impl $crate::message::RpcMsg<$service> for $m_input {
type Response = $m_output;
}
};
($service:ident, ServerStreaming, $m_input:ident, _, $m_output:ident) => {
impl $crate::message::Msg<$service> for $m_input {
type Pattern = $crate::message::ServerStreaming;
}
impl $crate::message::ServerStreamingMsg<$service> for $m_input {
type Response = $m_output;
}
};
($service:ident, ClientStreaming, $m_input:ident, $m_update:ident, $m_output:ident) => {
impl $crate::message::Msg<$service> for $m_input {
type Pattern = $crate::message::ClientStreaming;
}
impl $crate::message::ClientStreamingMsg<$service> for $m_input {
type Response = $m_output;
type Update = $m_update;
}
};
($service:ident, BidiStreaming, $m_input:ident, $m_update:ident, $m_output:ident) => {
impl $crate::message::Msg<$service> for $m_input {
type Pattern = $crate::message::BidiStreaming;
}
impl $crate::message::BidiStreamingMsg<$service> for $m_input {
type Response = $m_output;
type Update = $m_update;
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rpc_invoke {
(Rpc, $m_name:ident, $target_ty:ident, $msg:ident, $chan:ident, $target:ident) => {
$chan.rpc($msg, $target, $target_ty::$m_name).await
};
(ClientStreaming, $m_name:ident, $target_ty:ident, $msg:ident, $chan:ident, $target:ident) => {
$chan
.client_streaming($msg, $target, $target_ty::$m_name)
.await
};
(ServerStreaming, $m_name:ident, $target_ty:ident, $msg:ident, $chan:ident, $target:ident) => {
$chan
.server_streaming($msg, $target, $target_ty::$m_name)
.await
};
(BidiStreaming, $m_name:ident, $target_ty:ident, $msg:ident, $chan:ident, $target:ident) => {
$chan
.bidi_streaming($msg, $target, $target_ty::$m_name)
.await
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __derive_create_client{
(
$service:ident,
_,
[ $($tt:tt)* ]
) => {};
(
$service:ident,
$create_client:tt,
[ $($m_pattern:ident $m_name:ident = $m_input:ident, $m_update:tt -> $m_output:ident);+ ]
) => {
#[doc = concat!("Create an RPC client for ", stringify!($service), "\n\nSee the docs for [quic_rpc::rpc_service] for usage docs.")]
#[macro_export]
macro_rules! $create_client {
($struct:ident) => {
#[derive(::std::clone::Clone, ::std::fmt::Debug)]
pub struct $struct<C: $crate::Listener<$service>>(pub $crate::client::RpcClient<$service, C>);
impl<C: $crate::Listener<$service>> $struct<C> {
$(
$crate::__rpc_method!($m_pattern, $service, $m_name, $m_input, $m_output, $m_update);
)*
}
};
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __rpc_method {
(Rpc, $service:ident, $m_name:ident, $m_input:ident, $m_output:ident, _) => {
pub async fn $m_name(
&mut self,
input: $m_input,
) -> ::std::result::Result<$m_output, $crate::client::RpcClientError<C>> {
self.0.rpc(input).await
}
};
(ClientStreaming, $service:ident, $m_name:ident, $m_input:ident, $m_output:ident, $m_update:ident) => {
pub async fn $m_name(
&mut self,
input: $m_input,
) -> ::std::result::Result<
(
$crate::client::UpdateSink<$service, C, $m_input>,
::futures::future::BoxFuture<
'static,
::std::result::Result<$m_output, $crate::client::ClientStreamingItemError<C>>,
>,
),
$crate::client::ClientStreamingError<C>,
> {
self.0.client_streaming(input).await
}
};
(ServerStreaming, $service:ident, $m_name:ident, $m_input:ident, $m_output:ident, _) => {
pub async fn $m_name(
&mut self,
input: $m_input,
) -> ::std::result::Result<
::futures::stream::BoxStream<
'static,
::std::result::Result<$m_output, $crate::client::StreamingResponseItemError<C>>,
>,
$crate::client::StreamingResponseError<C>,
> {
self.0.server_streaming(input).await
}
};
(BidiStreaming, $service:ident, $m_name:ident, $m_input:ident, $m_output:ident, $m_update:ident) => {
pub async fn $m_name(
&mut self,
input: $m_input,
) -> ::std::result::Result<
(
$crate::client::UpdateSink<$service, C, $m_input>,
::futures::stream::BoxStream<
'static,
::std::result::Result<$m_output, $crate::client::BidiItemError<C>>,
>,
),
$crate::client::BidiError<C>,
> {
self.0.bidi(input).await
}
};
}