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
//! Used to manage application state.

#![deny(missing_docs)]

use std::sync::{Arc, RwLock, RwLockReadGuard};

/// Holds application state.
///
/// # Cloning
///
/// It can be useful to clone `AppStateWrapper`'s in order to pass state into event handler
/// closures.
///
/// All clones will point to the same inner state.
///
/// Cloning an `AppStateWrapper` is a very cheap operation.
pub struct AppStateWrapper<S: AppState>(Arc<RwLock<S>>);

/// Application state.
pub trait AppState {
    /// Indicates that something has happened.
    ///
    /// ```
    /// # use std::time::SystemTime;
    /// #[allow(unused)]
    /// enum MyMessageType {
    ///     IncreaseClickCounter,
    ///     SetLastPausedAt(SystemTime)
    /// }
    /// ```
    type Message;

    /// Send a message to the state object.
    /// This will usually lead to a state update
    fn msg(&mut self, message: Self::Message);
}

impl<S: AppState> AppStateWrapper<S> {
    /// Create a new AppStateWrapper.
    pub fn new(state: S) -> Self {
        Self(Arc::new(RwLock::new(state)))
    }

    /// Acquire write access to the AppState then send a message.
    pub fn msg(&mut self, msg: S::Message) {
        self.0.write().unwrap().msg(msg);
    }

    /// Acquire read access to AppState.
    pub fn read(&self) -> RwLockReadGuard<'_, S> {
        self.0.read().unwrap()
    }
}

impl<S: AppState> Clone for AppStateWrapper<S> {
    fn clone(&self) -> Self {
        AppStateWrapper(Arc::clone(&self.0))
    }
}