Skip to main content

percy_state/
lib.rs

1//! Used to manage application state.
2
3#![deny(missing_docs)]
4
5use std::sync::{Arc, RwLock, RwLockReadGuard};
6
7/// Holds application state.
8///
9/// # Cloning
10///
11/// It can be useful to clone `AppStateWrapper`'s in order to pass state into event handler
12/// closures.
13///
14/// All clones will point to the same inner state.
15///
16/// Cloning an `AppStateWrapper` is a very cheap operation.
17pub struct AppStateWrapper<S: AppState>(Arc<RwLock<S>>);
18
19/// Application state.
20pub trait AppState {
21    /// Indicates that something has happened.
22    ///
23    /// ```
24    /// # use std::time::SystemTime;
25    /// #[allow(unused)]
26    /// enum MyMessageType {
27    ///     IncreaseClickCounter,
28    ///     SetLastPausedAt(SystemTime)
29    /// }
30    /// ```
31    type Message;
32
33    /// Send a message to the state object.
34    /// This will usually lead to a state update
35    fn msg(&mut self, message: Self::Message);
36}
37
38impl<S: AppState> AppStateWrapper<S> {
39    /// Create a new AppStateWrapper.
40    pub fn new(state: S) -> Self {
41        Self(Arc::new(RwLock::new(state)))
42    }
43
44    /// Acquire write access to the AppState then send a message.
45    pub fn msg(&mut self, msg: S::Message) {
46        self.0.write().unwrap().msg(msg);
47    }
48
49    /// Acquire read access to AppState.
50    pub fn read(&self) -> RwLockReadGuard<'_, S> {
51        self.0.read().unwrap()
52    }
53}
54
55impl<S: AppState> Clone for AppStateWrapper<S> {
56    fn clone(&self) -> Self {
57        AppStateWrapper(Arc::clone(&self.0))
58    }
59}