arrpc_core/
lib.rs

1use std::ops::Deref;
2
3use anyhow::Context;
4use async_trait::async_trait;
5use serde::{de::DeserializeOwned, Serialize};
6
7pub use anyhow::Result;
8
9#[async_trait]
10pub trait Service {
11    async fn accept<R>(&self, req: R) -> Result<R::Response>
12    where
13        R: Request + Send + Sync;
14}
15
16#[async_trait]
17pub trait ServiceContract: MakeClient {
18    type R: Request + Send + Sync;
19    async fn eval(&self, req: &Self::R) -> Result<()>;
20}
21
22#[async_trait]
23pub trait ClientContract {
24    async fn send<R, V>(&self, req: R) -> Result<V>
25    where
26        R: Serialize + Send + Sync,
27        V: DeserializeOwned + Send + Sync;
28}
29
30pub trait Request {
31    type Response;
32    fn proc<P: DeserializeOwned>(&self) -> Result<P>;
33    fn respond<V: Serialize>(self, value: V) -> Result<Self::Response>;
34}
35
36pub struct UniversalClient<T>(pub T);
37
38pub struct UniversalServer<Contract, Service> {
39    pub contract: Contract,
40    pub service: Service,
41}
42
43impl<C, S> UniversalServer<C, S>
44where
45    C: ServiceContract,
46    S: Deref,
47    S::Target: Service,
48{
49    pub async fn accept(&self, req: C::R) -> Result<<C::R as Request>::Response> {
50        self.contract
51            .eval(&req)
52            .await
53            .context("verifying contract")?;
54
55        self.service
56            .accept(req)
57            .await
58            .context("service called with proc")
59    }
60}
61
62pub trait MakeClient {
63    type Args;
64    type Client: ClientContract;
65
66    fn make_client<A>(args: A) -> UniversalClient<Self::Client>
67    where
68        Self::Args: From<A>;
69}