a3s_boot/pipeline/
interceptor.rs1use super::ExecutionContext;
2use crate::{BootResponse, BoxFuture, Result};
3use std::sync::Arc;
4
5pub trait Interceptor: Send + Sync + 'static {
7 fn before(&self, _context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
8 Box::pin(async { Ok(()) })
9 }
10
11 fn short_circuit(
12 &self,
13 _context: ExecutionContext,
14 ) -> BoxFuture<'static, Result<Option<BootResponse>>> {
15 Box::pin(async { Ok(None) })
16 }
17
18 fn after(
19 &self,
20 _context: ExecutionContext,
21 response: BootResponse,
22 ) -> BoxFuture<'static, Result<BootResponse>> {
23 Box::pin(async move { Ok(response) })
24 }
25}
26
27impl<F, Fut> Interceptor for F
28where
29 F: Fn(ExecutionContext) -> Fut + Send + Sync + 'static,
30 Fut: std::future::Future<Output = Result<()>> + Send + 'static,
31{
32 fn before(&self, context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
33 Box::pin(self(context))
34 }
35}
36
37pub trait ExecutionInterceptor: Send + Sync + 'static {
39 fn before(&self, _context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
40 Box::pin(async { Ok(()) })
41 }
42
43 fn after(&self, _context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
44 Box::pin(async { Ok(()) })
45 }
46}
47
48impl<F, Fut> ExecutionInterceptor for F
49where
50 F: Fn(ExecutionContext) -> Fut + Send + Sync + 'static,
51 Fut: std::future::Future<Output = Result<()>> + Send + 'static,
52{
53 fn before(&self, context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
54 Box::pin(self(context))
55 }
56}
57
58impl ExecutionInterceptor for Arc<dyn ExecutionInterceptor> {
59 fn before(&self, context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
60 self.as_ref().before(context)
61 }
62
63 fn after(&self, context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
64 self.as_ref().after(context)
65 }
66}
67
68pub(crate) struct ExecutionInterceptorAdapter<I> {
69 inner: I,
70}
71
72impl<I> ExecutionInterceptorAdapter<I> {
73 pub(crate) fn new(inner: I) -> Self {
74 Self { inner }
75 }
76}
77
78impl<I> Interceptor for ExecutionInterceptorAdapter<I>
79where
80 I: ExecutionInterceptor,
81{
82 fn before(&self, context: ExecutionContext) -> BoxFuture<'static, Result<()>> {
83 self.inner.before(context)
84 }
85
86 fn after(
87 &self,
88 context: ExecutionContext,
89 response: BootResponse,
90 ) -> BoxFuture<'static, Result<BootResponse>> {
91 let future = self.inner.after(context);
92 Box::pin(async move {
93 future.await?;
94 Ok(response)
95 })
96 }
97}