tarpc_copy/server/request_hook/
before.rs1use crate::{context, server::Serve, ServerError};
10use futures::prelude::*;
11
12#[allow(async_fn_in_trait)]
14pub trait BeforeRequest<Req> {
15 async fn before(&mut self, ctx: &mut context::Context, req: &Req) -> Result<(), ServerError>;
23}
24
25pub trait BeforeRequestList<Req>: BeforeRequest<Req> {
27 type Then<Next>: BeforeRequest<Req>
29 where
30 Next: BeforeRequest<Req>;
31
32 fn then<Next: BeforeRequest<Req>>(self, next: Next) -> Self::Then<Next>;
34
35 fn then_fn<
37 Next: FnMut(&mut context::Context, &Req) -> Fut,
38 Fut: Future<Output = Result<(), ServerError>>,
39 >(
40 self,
41 next: Next,
42 ) -> Self::Then<Next>
43 where
44 Self: Sized,
45 {
46 self.then(next)
47 }
48
49 type Serve<S: Serve<Req = Req>>: Serve<Req = Req>;
51
52 fn serving<S: Serve<Req = Req>>(self, serve: S) -> Self::Serve<S>;
55}
56
57impl<F, Fut, Req> BeforeRequest<Req> for F
58where
59 F: FnMut(&mut context::Context, &Req) -> Fut,
60 Fut: Future<Output = Result<(), ServerError>>,
61{
62 async fn before(&mut self, ctx: &mut context::Context, req: &Req) -> Result<(), ServerError> {
63 self(ctx, req).await
64 }
65}
66
67#[derive(Clone)]
69pub struct HookThenServe<Serv, Hook> {
70 serve: Serv,
71 hook: Hook,
72}
73
74impl<Serv, Hook> HookThenServe<Serv, Hook> {
75 pub(crate) fn new(serve: Serv, hook: Hook) -> Self {
76 Self { serve, hook }
77 }
78}
79
80impl<Serv, Hook> Serve for HookThenServe<Serv, Hook>
81where
82 Serv: Serve,
83 Hook: BeforeRequest<Serv::Req>,
84{
85 type Req = Serv::Req;
86 type Resp = Serv::Resp;
87
88 async fn serve(
89 self,
90 mut ctx: context::Context,
91 req: Self::Req,
92 ) -> Result<Serv::Resp, ServerError> {
93 let HookThenServe {
94 serve, mut hook, ..
95 } = self;
96 hook.before(&mut ctx, &req).await?;
97 serve.serve(ctx, req).await
98 }
99}
100
101pub fn before() -> BeforeRequestNil {
129 BeforeRequestNil
130}
131
132#[derive(Clone, Copy)]
134pub struct BeforeRequestCons<First, Rest>(First, Rest);
135
136#[derive(Clone, Copy)]
138pub struct BeforeRequestNil;
139
140impl<Req, First: BeforeRequest<Req>, Rest: BeforeRequest<Req>> BeforeRequest<Req>
141 for BeforeRequestCons<First, Rest>
142{
143 async fn before(&mut self, ctx: &mut context::Context, req: &Req) -> Result<(), ServerError> {
144 let BeforeRequestCons(first, rest) = self;
145 first.before(ctx, req).await?;
146 rest.before(ctx, req).await?;
147 Ok(())
148 }
149}
150
151impl<Req> BeforeRequest<Req> for BeforeRequestNil {
152 async fn before(&mut self, _: &mut context::Context, _: &Req) -> Result<(), ServerError> {
153 Ok(())
154 }
155}
156
157impl<Req, First: BeforeRequest<Req>, Rest: BeforeRequestList<Req>> BeforeRequestList<Req>
158 for BeforeRequestCons<First, Rest>
159{
160 type Then<Next> = BeforeRequestCons<First, Rest::Then<Next>> where Next: BeforeRequest<Req>;
161
162 fn then<Next: BeforeRequest<Req>>(self, next: Next) -> Self::Then<Next> {
163 let BeforeRequestCons(first, rest) = self;
164 BeforeRequestCons(first, rest.then(next))
165 }
166
167 type Serve<S: Serve<Req = Req>> = HookThenServe<S, Self>;
168
169 fn serving<S: Serve<Req = Req>>(self, serve: S) -> Self::Serve<S> {
170 HookThenServe::new(serve, self)
171 }
172}
173
174impl<Req> BeforeRequestList<Req> for BeforeRequestNil {
175 type Then<Next> = BeforeRequestCons<Next, BeforeRequestNil> where Next: BeforeRequest<Req>;
176
177 fn then<Next: BeforeRequest<Req>>(self, next: Next) -> Self::Then<Next> {
178 BeforeRequestCons(next, BeforeRequestNil)
179 }
180
181 type Serve<S: Serve<Req = Req>> = S;
182
183 fn serving<S: Serve<Req = Req>>(self, serve: S) -> S {
184 serve
185 }
186}
187
188#[test]
189fn before_request_list() {
190 use crate::server::serve;
191 use futures::executor::block_on;
192 use std::cell::Cell;
193
194 let i = Cell::new(0);
195 let serve = before()
196 .then_fn(|_, _| async {
197 assert!(i.get() == 0);
198 i.set(1);
199 Ok(())
200 })
201 .then_fn(|_, _| async {
202 assert!(i.get() == 1);
203 i.set(2);
204 Ok(())
205 })
206 .serving(serve(|_ctx, i| async move { Ok(i + 1) }));
207 let response = serve.clone().serve(context::current(), 1);
208 assert!(block_on(response).is_ok());
209 assert!(i.get() == 2);
210}