use serde::{Deserialize, Serialize};
use std::{error::Error, fmt};
use crate::{
chmux,
rch::{base, oneshot},
};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CallError {
Dropped,
RemoteReceive(base::RecvError),
RemoteConnect(chmux::ConnectError),
RemoteListen(chmux::ListenerError),
}
impl fmt::Display for CallError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Dropped => write!(f, "provider dropped or function panicked"),
Self::RemoteReceive(err) => write!(f, "receive error: {err}"),
Self::RemoteConnect(err) => write!(f, "connect error: {err}"),
Self::RemoteListen(err) => write!(f, "listen error: {err}"),
}
}
}
impl From<oneshot::RecvError> for CallError {
fn from(err: oneshot::RecvError) -> Self {
match err {
oneshot::RecvError::Closed => Self::Dropped,
oneshot::RecvError::RemoteReceive(err) => Self::RemoteReceive(err),
oneshot::RecvError::RemoteConnect(err) => Self::RemoteConnect(err),
oneshot::RecvError::RemoteListen(err) => Self::RemoteListen(err),
}
}
}
impl Error for CallError {}
macro_rules! arg_stub {
($name:ident, $fn_type:ident, $provider_type:ident, $new:ident, $provided:ident, ( $( $self_prefix:tt )* ), $( $arg:ident : $arg_type:ident ),*) => {
impl < $( $arg_type , )* R, Codec> $name < ($($arg_type ,)*), R, Codec>
where
$( $arg_type : RemoteSend ,)*
R: RemoteSend,
Codec: codec::Codec,
{
#[allow(unused_mut)]
pub fn $new <F, Fut>(mut fun: F) -> Self
where
F: $fn_type ($($arg_type),*) -> Fut + Send + Sync + 'static,
Fut: Future<Output = R> + Send,
{
Self::new_int(move |( $($arg ,)* )| fun($($arg),*))
}
#[allow(unused_mut)]
pub fn $provided <F, Fut>(mut fun: F) -> (Self, $provider_type)
where
F: $fn_type ($($arg_type),*) -> Fut + Send + Sync + 'static,
Fut: Future<Output = R> + Send,
{
Self::provided_int(move |( $($arg ,)* )| fun($($arg),*))
}
#[allow(clippy::too_many_arguments)]
pub async fn try_call( $( $self_prefix )* self, $( $arg : $arg_type ),* ) -> Result<R, CallError> {
self.try_call_int(( $($arg ,)* )).await
}
}
impl < $($arg_type ,)* RT, RE, Codec> $name < ($($arg_type ,)* ), Result<RT, RE>, Codec>
where
$( $arg_type : RemoteSend ,)*
RT: RemoteSend,
RE: RemoteSend + From<CallError>,
Codec: codec::Codec,
{
#[allow(clippy::too_many_arguments)]
pub async fn call($( $self_prefix )* self, $( $arg : $arg_type ),*) -> Result<RT, RE> {
self.call_int(( $($arg ,)* )).await
}
}
};
}
mod msg;
mod rfn_const;
mod rfn_mut;
mod rfn_once;
pub use rfn_const::{RFn, RFnProvider};
pub use rfn_mut::{RFnMut, RFnMutProvider};
pub use rfn_once::{RFnOnce, RFnOnceProvider};