Skip to main content

sword_core/layers/
stack.rs

1use crate::State;
2use axum::{Router, extract::Request, response::IntoResponse, routing::Route};
3use std::convert::Infallible;
4use tower::{Layer, Service};
5
6type LayerFn<S> = Box<dyn Fn(Router<S>) -> Router<S> + Send + Sync>;
7
8/// A stack for managing and applying middleware layers to a router.
9///
10/// `LayerStack` provides a way to accumulate layers and apply them to a router in the
11/// order they were added. Layers are applied via the `push()` method during configuration,
12/// and then applied to the router via `apply()` during the build phase.
13pub struct LayerStack<S = State> {
14    layers: Vec<LayerFn<S>>,
15}
16
17impl<S> LayerStack<S>
18where
19    S: Clone + Send + Sync + 'static,
20{
21    pub fn new() -> Self {
22        Self { layers: Vec::new() }
23    }
24
25    /// Add a layer to the stack.
26    ///
27    /// Layers are applied in FIFO order when `apply()` is called. Each layer will
28    /// wrap the router after all adapters have been registered.
29    pub fn push<L>(&mut self, layer: L)
30    where
31        L: Layer<Route> + Clone + Send + Sync + 'static,
32        L::Service: Service<Request> + Clone + Send + Sync + 'static,
33        <L::Service as Service<Request>>::Response: IntoResponse + 'static,
34        <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
35        <L::Service as Service<Request>>::Future: Send + 'static,
36    {
37        self.layers.push(Box::new(move |router: Router<S>| {
38            router.layer(layer.clone())
39        }));
40    }
41
42    /// Apply all layers to the given router.
43    ///
44    /// Layers are applied in FIFO order (first pushed = first applied = outermost).
45    pub fn apply(self, mut router: Router<S>) -> Router<S> {
46        for layer_fn in self.layers {
47            router = layer_fn(router);
48        }
49        router
50    }
51}
52
53impl<S> Default for LayerStack<S>
54where
55    S: Clone + Send + Sync + 'static,
56{
57    fn default() -> Self {
58        Self::new()
59    }
60}