1use calls::Metadata;
4use types::{Request, Response, Call, Output};
5use futures::{future::Either, Future};
6
7pub trait Middleware<M: Metadata>: Send + Sync + 'static {
9 type Future: Future<Item=Option<Response>, Error=()> + Send + 'static;
11
12 type CallFuture: Future<Item=Option<Output>, Error=()> + Send + 'static;
14
15 fn on_request<F, X>(&self, request: Request, meta: M, next: F) -> Either<Self::Future, X> where
19 F: FnOnce(Request, M) -> X + Send,
20 X: Future<Item=Option<Response>, Error=()> + Send + 'static,
21 {
22 Either::B(next(request, meta))
23 }
24
25 fn on_call<F, X>(&self, call: Call, meta: M, next: F) -> Either<Self::CallFuture, X> where
29 F: FnOnce(Call, M) -> X + Send,
30 X: Future<Item=Option<Output>, Error=()> + Send + 'static,
31 {
32 Either::B(next(call, meta))
33 }
34}
35
36pub type NoopFuture = Box<Future<Item=Option<Response>, Error=()> + Send>;
38pub type NoopCallFuture = Box<Future<Item=Option<Output>, Error=()> + Send>;
40
41#[derive(Debug, Default)]
43pub struct Noop;
44impl<M: Metadata> Middleware<M> for Noop {
45 type Future = NoopFuture;
46 type CallFuture = NoopCallFuture;
47}
48
49impl<M: Metadata, A: Middleware<M>, B: Middleware<M>>
50 Middleware<M> for (A, B)
51{
52 type Future = Either<A::Future, B::Future>;
53 type CallFuture = Either<A::CallFuture, B::CallFuture>;
54
55 fn on_request<F, X>(&self, request: Request, meta: M, process: F) -> Either<Self::Future, X> where
56 F: FnOnce(Request, M) -> X + Send,
57 X: Future<Item=Option<Response>, Error=()> + Send + 'static,
58 {
59 repack(self.0.on_request(request, meta, move |request, meta| {
60 self.1.on_request(request, meta, process)
61 }))
62 }
63
64 fn on_call<F, X>(&self, call: Call, meta: M, process: F) -> Either<Self::CallFuture, X> where
65 F: FnOnce(Call, M) -> X + Send,
66 X: Future<Item=Option<Output>, Error=()> + Send + 'static,
67 {
68 repack(self.0.on_call(call, meta, move |call, meta| {
69 self.1.on_call(call, meta, process)
70 }))
71 }
72}
73
74impl<M: Metadata, A: Middleware<M>, B: Middleware<M>, C: Middleware<M>>
75 Middleware<M> for (A, B, C)
76{
77 type Future = Either<A::Future, Either<B::Future, C::Future>>;
78 type CallFuture = Either<A::CallFuture, Either<B::CallFuture, C::CallFuture>>;
79
80 fn on_request<F, X>(&self, request: Request, meta: M, process: F) -> Either<Self::Future, X> where
81 F: FnOnce(Request, M) -> X + Send,
82 X: Future<Item=Option<Response>, Error=()> + Send + 'static,
83 {
84 repack(self.0.on_request(request, meta, move |request, meta| {
85 repack(self.1.on_request(request, meta, move |request, meta| {
86 self.2.on_request(request, meta, process)
87 }))
88 }))
89 }
90
91 fn on_call<F, X>(&self, call: Call, meta: M, process: F) -> Either<Self::CallFuture, X> where
92 F: FnOnce(Call, M) -> X + Send,
93 X: Future<Item=Option<Output>, Error=()> + Send + 'static,
94 {
95 repack(self.0.on_call(call, meta, move |call, meta| {
96 repack(self.1.on_call(call, meta, move |call, meta| {
97 self.2.on_call(call, meta, process)
98 }))
99 }))
100 }
101}
102
103impl<M: Metadata, A: Middleware<M>, B: Middleware<M>, C: Middleware<M>, D: Middleware<M>>
104 Middleware<M> for (A, B, C, D)
105{
106 type Future = Either<A::Future, Either<B::Future, Either<C::Future, D::Future>>>;
107 type CallFuture = Either<A::CallFuture, Either<B::CallFuture, Either<C::CallFuture, D::CallFuture>>>;
108
109 fn on_request<F, X>(&self, request: Request, meta: M, process: F) -> Either<Self::Future, X> where
110 F: FnOnce(Request, M) -> X + Send,
111 X: Future<Item=Option<Response>, Error=()> + Send + 'static,
112 {
113 repack(self.0.on_request(request, meta, move |request, meta| {
114 repack(self.1.on_request(request, meta, move |request, meta| {
115 repack(self.2.on_request(request, meta, move |request, meta| {
116 self.3.on_request(request, meta, process)
117 }))
118 }))
119 }))
120 }
121
122 fn on_call<F, X>(&self, call: Call, meta: M, process: F) -> Either<Self::CallFuture, X> where
123 F: FnOnce(Call, M) -> X + Send,
124 X: Future<Item=Option<Output>, Error=()> + Send + 'static,
125 {
126 repack(self.0.on_call(call, meta, move |call, meta| {
127 repack(self.1.on_call(call, meta, move |call, meta| {
128 repack(self.2.on_call(call, meta, move |call, meta| {
129 self.3.on_call(call, meta, process)
130 }))
131 }))
132 }))
133 }
134}
135
136#[inline(always)]
137fn repack<A, B, X>(result: Either<A, Either<B, X>>) -> Either<Either<A, B>, X> {
138 match result {
139 Either::A(a) => Either::A(Either::A(a)),
140 Either::B(Either::A(b)) => Either::A(Either::B(b)),
141 Either::B(Either::B(x)) => Either::B(x),
142 }
143}