1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! State driven middleware to enable attachment of values to request state.
//!
//! This module provides generics to enable attaching (appropriate) values to
//! the state of a request, through the use of `Middleware`. Middleware can
//! be created via `StateMiddleware::with`, with the provided value being the
//! value to attach to the request state.
use crate::handler::HandlerFuture;
use crate::middleware::{Middleware, NewMiddleware};
use crate::state::{State, StateData};
use std::panic::RefUnwindSafe;
use std::pin::Pin;

/// Middleware binding for generic types to enable easy shared state.
///
/// This acts as nothing more than a `Middleware` instance which will
/// attach a generic type to a request `State`, however it removes a
/// barrier for users to Gotham who might not know the internals.
///
/// The generic types inside this struct can (and will) be cloned
/// often, so wrap your expensive types in reference counts as needed.
#[derive(Clone)]
pub struct StateMiddleware<T>
where
    T: Clone + RefUnwindSafe + StateData + Sync,
{
    t: T,
}

/// Main implementation.
impl<T> StateMiddleware<T>
where
    T: Clone + RefUnwindSafe + StateData + Sync,
{
    /// Creates a new middleware binding, taking ownership of the state data.
    pub fn new(t: T) -> Self {
        Self { t }
    }
}

/// `Middleware` trait implementation.
impl<T> Middleware for StateMiddleware<T>
where
    T: Clone + RefUnwindSafe + StateData + Sync,
{
    /// Attaches the inner generic value to the request state.
    ///
    /// This will enable the `Handler` to borrow the value directly from the state.
    fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
    where
        Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,
    {
        state.put(self.t);
        chain(state)
    }
}

/// `NewMiddleware` trait implementation.
impl<T> NewMiddleware for StateMiddleware<T>
where
    T: Clone + RefUnwindSafe + StateData + Sync,
{
    type Instance = Self;

    /// Clones the current middleware to a new instance.
    fn new_middleware(&self) -> anyhow::Result<Self::Instance> {
        Ok(self.clone())
    }
}