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