app_state/states/
traits.rs

1use crate::states::{find_state, find_state_unwrap, insert_state, insert_state_if_not_exists};
2use std::error::Error;
3
4pub trait InitAppState {
5    fn init_app_state(self);
6}
7
8pub trait InitMutAppState {
9    fn init_mut_app_state(self);
10}
11
12pub trait CreateAppState<T: 'static + Send> {
13    fn new(state: T) -> Self;
14}
15
16pub trait AppStateTrait<T, U>
17where
18    T: 'static + Send,
19    U: 'static + AppStateTrait<T, U> + CreateAppState<T> + Clone + Send,
20{
21    /// Initializes the state store with the given state.
22    /// If the state store has already been initialized, this will overwrite the existing state.
23    ///
24    /// # Examples
25    /// ```rust
26    /// use app_state::{AppState, AppStateTrait};
27    ///
28    /// struct MyState {
29    ///   counter: u32,
30    /// }
31    ///
32    /// fn main() {
33    ///   let state = MyState { counter: 0 };
34    ///   AppState::init(state);
35    /// }
36    /// ```
37    fn init(state: T) {
38        #[cfg(feature = "log")]
39        log::debug!("Initializing state {}", std::any::type_name::<T>());
40
41        insert_state(U::new(state));
42    }
43
44    /// Initializes the state store with the given state.
45    /// If the state store has already been initialized, this will do nothing.
46    /// This is useful for initializing the state store with a default state.
47    /// If you want to overwrite the existing state, use `init` instead.
48    ///
49    /// # Examples
50    /// ```rust
51    /// use app_state::{AppState, AppStateTrait};
52    ///
53    /// struct MyState {
54    ///   counter: u32,
55    /// }
56    ///
57    /// fn main() {
58    ///   AppState::init_if_not_exists(|| MyState { counter: 0 });
59    /// }
60    /// ```
61    fn init_if_not_exists<F: FnOnce() -> T>(state: F) {
62        insert_state_if_not_exists(|| {
63            #[cfg(feature = "log")]
64            log::debug!("Initializing state {}", std::any::type_name::<T>());
65
66            U::new(state())
67        });
68    }
69
70    /// Returns a reference to the state.
71    /// If the state store has not been initialized, this will panic.
72    fn get() -> U {
73        find_state_unwrap()
74    }
75
76    /// Returns a reference to the state.
77    /// If the state store has not been initialized, this will return `Err`.
78    fn try_get() -> Result<U, Box<dyn Error>> {
79        find_state()
80    }
81
82    /// Returns a reference to the state.
83    /// Inserts the supplied value if the state store has not been initialized.
84    fn get_or_insert(val: T) -> U {
85        insert_state_if_not_exists(|| {
86            #[cfg(feature = "log")]
87            log::debug!("Initializing state {}", std::any::type_name::<T>());
88
89            U::new(val)
90        })
91    }
92
93    /// Returns a reference to the state.
94    /// Inserts the supplied value if the state store has not been initialized.
95    fn get_or_insert_with<F: FnOnce() -> T>(f: F) -> U {
96        insert_state_if_not_exists(|| {
97            #[cfg(feature = "log")]
98            log::debug!("Initializing state {}", std::any::type_name::<T>());
99
100            U::new(f())
101        })
102    }
103
104    /// Returns a reference to the state.
105    /// Inserts the default value of `T` if the state store has not been initialized.
106    fn get_or_insert_default() -> U
107    where
108        T: Default,
109    {
110        insert_state_if_not_exists(|| {
111            #[cfg(feature = "log")]
112            log::debug!("Initializing state {}", std::any::type_name::<T>());
113
114            U::new(T::default())
115        })
116    }
117}