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