gotham/middleware/
state.rs

1//! State driven middleware to enable attachment of values to request state.
2//!
3//! This module provides generics to enable attaching (appropriate) values to
4//! the state of a request, through the use of `Middleware`. Middleware can
5//! be created via `StateMiddleware::with`, with the provided value being the
6//! value to attach to the request state.
7use crate::handler::HandlerFuture;
8use crate::middleware::{Middleware, NewMiddleware};
9use crate::state::{State, StateData};
10use std::panic::RefUnwindSafe;
11use std::pin::Pin;
12
13/// Middleware binding for generic types to enable easy shared state.
14///
15/// This acts as nothing more than a `Middleware` instance which will
16/// attach a generic type to a request `State`, however it removes a
17/// barrier for users to Gotham who might not know the internals.
18///
19/// The generic types inside this struct can (and will) be cloned
20/// often, so wrap your expensive types in reference counts as needed.
21#[derive(Clone)]
22pub struct StateMiddleware<T>
23where
24    T: Clone + RefUnwindSafe + StateData + Sync,
25{
26    t: T,
27}
28
29/// Main implementation.
30impl<T> StateMiddleware<T>
31where
32    T: Clone + RefUnwindSafe + StateData + Sync,
33{
34    /// Creates a new middleware binding, taking ownership of the state data.
35    pub fn new(t: T) -> Self {
36        Self { t }
37    }
38}
39
40/// `Middleware` trait implementation.
41impl<T> Middleware for StateMiddleware<T>
42where
43    T: Clone + RefUnwindSafe + StateData + Sync,
44{
45    /// Attaches the inner generic value to the request state.
46    ///
47    /// This will enable the `Handler` to borrow the value directly from the state.
48    fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
49    where
50        Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,
51    {
52        state.put(self.t);
53        chain(state)
54    }
55}
56
57/// `NewMiddleware` trait implementation.
58impl<T> NewMiddleware for StateMiddleware<T>
59where
60    T: Clone + RefUnwindSafe + StateData + Sync,
61{
62    type Instance = Self;
63
64    /// Clones the current middleware to a new instance.
65    fn new_middleware(&self) -> anyhow::Result<Self::Instance> {
66        Ok(self.clone())
67    }
68}