#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#[cfg(feature = "server")]
pub use inventory;
pub use serde;
#[derive(thiserror::Error, Debug, serde::Serialize, serde::Deserialize)]
pub enum RpcError<E, FE> {
#[error("no rpc endpoint found")]
NoEndpointFound,
#[error("server rpc deserialize error")]
ServerDeserializeError(#[source] FE),
#[error(transparent)]
HandlerError(#[from] E),
}
pub type RpcResult<T, E, FE> = Result<T, RpcError<E, FE>>;
pub trait RpcMethod<S: RpcService>: serde::Serialize + serde::de::DeserializeOwned {
type Response: serde::Serialize + serde::de::DeserializeOwned;
type Error: serde::Serialize + serde::de::DeserializeOwned;
const URI: &'static str;
}
pub trait RpcService {
type Format: RpcFormat;
}
pub trait RpcFormat {
type Error: 'static + serde::Serialize + serde::de::DeserializeOwned;
fn serialize_request<M: serde::Serialize>(val: M) -> Result<Vec<u8>, Self::Error>;
fn deserialize_request<M: serde::de::DeserializeOwned>(buffer: &[u8])
-> Result<M, Self::Error>;
fn serialize_response<R, E>(val: RpcResult<R, E, Self::Error>) -> Result<Vec<u8>, Self::Error>
where
R: serde::Serialize,
E: serde::Serialize;
fn deserialize_response<R, E>(
buffer: &[u8],
) -> Result<RpcResult<R, E, Self::Error>, Self::Error>
where
R: serde::de::DeserializeOwned,
E: serde::de::DeserializeOwned;
}
pub mod formats;
pub use formats::Json;
mod server;
#[cfg(feature = "server")]
pub use server::{find_rpc_handler, handle_rpc};
mod client;
pub use client::{ClientRpcError, ClientRpcService};
pub use marpc_macros::rpc;
pub mod internal {
use super::*;
pub use client::rpc_call;
pub use server::ServerRpcHandler;
pub use server::ServerRpcRegistryItem;
pub use server::ServerRpcService;
pub trait ResultTypes {
type Ok;
type Err;
}
impl<T, E> ResultTypes for Result<T, E> {
type Ok = T;
type Err = E;
}
}
#[cfg(feature = "server")]
#[macro_export]
macro_rules! register_service {
($service:ident) => {
$crate::register_service!($service with ());
};
($service:ident with $state:ty) => {
const _: () = {
pub struct ServiceRegistryItem {
cell: std::sync::OnceLock<$crate::internal::ServerRpcHandler<$service>>,
handler_fn: fn() -> $crate::internal::ServerRpcHandler<$service>,
}
$crate::inventory::collect!(&'static ServiceRegistryItem);
impl $service {
#[doc(hidden)]
pub const fn __rpc_call_internal_create_handler(
handler_fn: fn() -> $crate::internal::ServerRpcHandler<$service>,
) -> ServiceRegistryItem {
ServiceRegistryItem {
cell: std::sync::OnceLock::new(),
handler_fn,
}
}
}
impl $crate::internal::ServerRpcRegistryItem<$service> for ServiceRegistryItem {
fn handler(&self) -> &$crate::internal::ServerRpcHandler<$service> {
self.cell.get_or_init(|| (self.handler_fn)())
}
}
impl $crate::internal::ServerRpcService for $service {
type ServerState = $state;
type RegistryItem = ServiceRegistryItem;
}
};
};
}