1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*!
`serde-tc` is a library for de/serializing method invocations for trait objects.

`serde-tc-macro` provides a macro for generating various code for a particular trait defiiniation.
1. A dispatcher; it takes the method name and the arguemnts (an opaque string) and invokes the method on the object.
2. A encoder; it defines a copy of the methods of the trait. Instead of the original return types,
the newly defined methods return encoded strings that can be directly used by the dispatcher.

`serde-tc` also provides a convenient module `http`,
which automatically builds a HTTP server using the given trait objects
to serve as a RPC server. The module also provides a `stub` implementation,
which can be used as the HTTP client when the server is built with the same trait.

Please refer to `serde-tc/tests/integration_tests.rs` for the actual usage.
*/

pub mod http;

use async_trait::async_trait;
pub use serde;
pub use serde_tc_macro::*;
use std::sync::Arc;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error<T: std::error::Error> {
    #[error("`{0}`")]
    MethodNotFound(String),
    #[error("`{0}`")]
    ArgumentNotFound(String),
    #[error("`{0}`")]
    Parse(T),
}

pub trait DispatchStringTuple {
    type Error: std::error::Error;
    fn dispatch(&self, method: &str, arguments: &str) -> Result<String, Error<Self::Error>>;
}

pub trait DispatchStringDict {
    type Error: std::error::Error;
    type Poly;
    fn dispatch(&self, method: &str, arguments: &str) -> Result<String, Error<Self::Error>>;
}

#[async_trait]
pub trait DispatchStringTupleAsync {
    type Error: std::error::Error;
    async fn dispatch(&self, method: &str, arguments: &str) -> Result<String, Error<Self::Error>>;
}

#[async_trait]
pub trait DispatchStringDictAsync {
    type Error: std::error::Error;
    type Poly;
    async fn dispatch(&self, method: &str, arguments: &str) -> Result<String, Error<Self::Error>>;
}

#[async_trait]
impl<T> DispatchStringDictAsync for Arc<T>
where
    T: DispatchStringDictAsync + Send + Sync + 'static + ?Sized,
{
    type Error = T::Error;
    type Poly = T::Poly;
    async fn dispatch(&self, method: &str, arguments: &str) -> Result<String, Error<Self::Error>> {
        (self.as_ref() as &T).dispatch(method, arguments).await
    }
}

#[async_trait]
impl<T> DispatchStringTupleAsync for Arc<T>
where
    T: DispatchStringTupleAsync + Send + Sync + 'static + ?Sized,
{
    type Error = T::Error;
    async fn dispatch(&self, method: &str, arguments: &str) -> Result<String, Error<Self::Error>> {
        (self.as_ref() as &T).dispatch(method, arguments).await
    }
}

#[async_trait]
pub trait StubCall: Send + Sync {
    type Error;

    async fn call(&self, method: &'static str, params: String) -> Result<String, Self::Error>;
}