1 use crate::types::{Error, Params, Value};
2 use crate::BoxFuture;
3 use std::fmt;
4 use std::future::Future;
5 use std::sync::Arc;
6 
7 /// Metadata trait
8 pub trait Metadata: Clone + Send + 'static {}
9 impl Metadata for () {}
10 impl<T: Metadata> Metadata for Option<T> {}
11 impl<T: Metadata> Metadata for Box<T> {}
12 impl<T: Sync + Send + 'static> Metadata for Arc<T> {}
13 
14 /// A future-conversion trait.
15 pub trait WrapFuture<T, E> {
16 	/// Convert itself into a boxed future.
into_future(self) -> BoxFuture<Result<T, E>>17 	fn into_future(self) -> BoxFuture<Result<T, E>>;
18 }
19 
20 impl<T: Send + 'static, E: Send + 'static> WrapFuture<T, E> for Result<T, E> {
into_future(self) -> BoxFuture<Result<T, E>>21 	fn into_future(self) -> BoxFuture<Result<T, E>> {
22 		Box::pin(async { self })
23 	}
24 }
25 
26 impl<T, E> WrapFuture<T, E> for BoxFuture<Result<T, E>> {
into_future(self) -> BoxFuture<Result<T, E>>27 	fn into_future(self) -> BoxFuture<Result<T, E>> {
28 		self
29 	}
30 }
31 
32 /// A synchronous or asynchronous method.
33 pub trait RpcMethodSync: Send + Sync + 'static {
34 	/// Call method
call(&self, params: Params) -> BoxFuture<crate::Result<Value>>35 	fn call(&self, params: Params) -> BoxFuture<crate::Result<Value>>;
36 }
37 
38 /// Asynchronous Method
39 pub trait RpcMethodSimple: Send + Sync + 'static {
40 	/// Output future
41 	type Out: Future<Output = Result<Value, Error>> + Send;
42 	/// Call method
call(&self, params: Params) -> Self::Out43 	fn call(&self, params: Params) -> Self::Out;
44 }
45 
46 /// Asynchronous Method with Metadata
47 pub trait RpcMethod<T: Metadata>: Send + Sync + 'static {
48 	/// Call method
call(&self, params: Params, meta: T) -> BoxFuture<crate::Result<Value>>49 	fn call(&self, params: Params, meta: T) -> BoxFuture<crate::Result<Value>>;
50 }
51 
52 /// Notification
53 pub trait RpcNotificationSimple: Send + Sync + 'static {
54 	/// Execute notification
execute(&self, params: Params)55 	fn execute(&self, params: Params);
56 }
57 
58 /// Notification with Metadata
59 pub trait RpcNotification<T: Metadata>: Send + Sync + 'static {
60 	/// Execute notification
execute(&self, params: Params, meta: T)61 	fn execute(&self, params: Params, meta: T);
62 }
63 
64 /// Possible Remote Procedures with Metadata
65 #[derive(Clone)]
66 pub enum RemoteProcedure<T: Metadata> {
67 	/// A method call
68 	Method(Arc<dyn RpcMethod<T>>),
69 	/// A notification
70 	Notification(Arc<dyn RpcNotification<T>>),
71 	/// An alias to other method,
72 	Alias(String),
73 }
74 
75 impl<T: Metadata> fmt::Debug for RemoteProcedure<T> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result76 	fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
77 		use self::RemoteProcedure::*;
78 		match *self {
79 			Method(..) => write!(fmt, "<method>"),
80 			Notification(..) => write!(fmt, "<notification>"),
81 			Alias(ref alias) => write!(fmt, "alias => {:?}", alias),
82 		}
83 	}
84 }
85 
86 impl<F: Send + Sync + 'static, X: Send + 'static> RpcMethodSimple for F
87 where
88 	F: Fn(Params) -> X,
89 	X: Future<Output = Result<Value, Error>>,
90 {
91 	type Out = X;
call(&self, params: Params) -> Self::Out92 	fn call(&self, params: Params) -> Self::Out {
93 		self(params)
94 	}
95 }
96 
97 impl<F: Send + Sync + 'static, X: Send + 'static> RpcMethodSync for F
98 where
99 	F: Fn(Params) -> X,
100 	X: WrapFuture<Value, Error>,
101 {
call(&self, params: Params) -> BoxFuture<crate::Result<Value>>102 	fn call(&self, params: Params) -> BoxFuture<crate::Result<Value>> {
103 		self(params).into_future()
104 	}
105 }
106 
107 impl<F: Send + Sync + 'static> RpcNotificationSimple for F
108 where
109 	F: Fn(Params),
110 {
execute(&self, params: Params)111 	fn execute(&self, params: Params) {
112 		self(params)
113 	}
114 }
115 
116 impl<F: Send + Sync + 'static, X: Send + 'static, T> RpcMethod<T> for F
117 where
118 	T: Metadata,
119 	F: Fn(Params, T) -> X,
120 	X: Future<Output = Result<Value, Error>>,
121 {
call(&self, params: Params, meta: T) -> BoxFuture<crate::Result<Value>>122 	fn call(&self, params: Params, meta: T) -> BoxFuture<crate::Result<Value>> {
123 		Box::pin(self(params, meta))
124 	}
125 }
126 
127 impl<F: Send + Sync + 'static, T> RpcNotification<T> for F
128 where
129 	T: Metadata,
130 	F: Fn(Params, T),
131 {
execute(&self, params: Params, meta: T)132 	fn execute(&self, params: Params, meta: T) {
133 		self(params, meta)
134 	}
135 }
136