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}