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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::fmt::{self, Debug};

use fmt::Formatter;

use crate::{async_trait, Conn, Handler};
/**
# A handler for sharing state across an application.

State is a handler that puts a clone of any `Clone + Send + Sync +
'static` type into every conn's state map.

```
use std::sync::{atomic::{AtomicBool, Ordering}, Arc};
use trillium::{Conn, State};
use trillium_testing::prelude::*;


#[derive(Clone, Default)] // Clone is mandatory
struct MyFeatureFlag(Arc<AtomicBool>);

impl MyFeatureFlag {
    pub fn is_enabled(&self) -> bool {
       self.0.load(Ordering::Relaxed)
    }

    pub fn toggle(&self) {
       self.0.fetch_xor(true, Ordering::Relaxed);
    }
}

let feature_flag = MyFeatureFlag::default();

let handler = (
    State::new(feature_flag.clone()),
    |conn: Conn| async move {
      if conn.state::<MyFeatureFlag>().unwrap().is_enabled() {
          conn.ok("feature enabled")
      } else {
          conn.ok("not enabled")
      }
    }
);

assert!(!feature_flag.is_enabled());
assert_ok!(get("/").on(&handler), "not enabled");
assert_ok!(get("/").on(&handler), "not enabled");
feature_flag.toggle();
assert!(feature_flag.is_enabled());
assert_ok!(get("/").on(&handler), "feature enabled");
assert_ok!(get("/").on(&handler), "feature enabled");

```

Please note that as with the above contrived example, if your state
needs to be mutable, you need to choose your own interior mutability
with whatever cross thread synchronization mechanisms are appropriate
for your application. There will be one clones of the contained T type
in memory for each http connection, and any locks should be held as
briefly as possible so as to minimize impact on other conns.

**Stability note:** This is a common enough pattern that it currently
exists in the public api, but may be removed at some point for
simplicity.
*/

pub struct State<T>(T);

impl<T: Debug> Debug for State<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_tuple("State").field(&self.0).finish()
    }
}

impl<T> Default for State<T>
where
    T: Default + Clone + Send + Sync + 'static,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<T> State<T>
where
    T: Clone + Send + Sync + 'static,
{
    /// Constructs a new State handler from any `Clone` + `Send` + `Sync` +
    /// `'static`
    #[allow(clippy::missing_const_for_fn)] // until const_fn stabilized
    pub fn new(t: T) -> Self {
        Self(t)
    }
}

/// Constructs a new [`State`] handler from any Clone + Send + Sync +
/// 'static. Alias for [`State::new`]
#[allow(clippy::missing_const_for_fn)] // until const_fn stabilized
pub fn state<T: Clone + Send + Sync + 'static>(t: T) -> State<T> {
    State::new(t)
}

#[async_trait]
impl<T: Clone + Send + Sync + 'static> Handler for State<T> {
    async fn run(&self, mut conn: Conn) -> Conn {
        conn.set_state(self.0.clone());
        conn
    }
}