atomic_hooks/
state_access.rs1use crate::hooks_state_functions::*;
2use std::marker::PhantomData;
3use crate::store::TopoKey;
4
5pub struct StateAccess<T> {
10 pub id: TopoKey,
11 _phantom_data: PhantomData<T>,
12}
13
14impl<T> std::fmt::Debug for StateAccess<T> {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 write!(f, "({:#?})", self.id)
17 }
18}
19
20impl<T> Copy for StateAccess<T> {}
21impl<T> Clone for StateAccess<T> {
22 fn clone(&self) -> StateAccess<T> {
23 StateAccess::<T> {
24 id: self.id,
25 _phantom_data: PhantomData::<T>,
26 }
27 }
28}
29
30impl<T> StateAccess<T>
31where
32 T: 'static,
33{
34 pub fn new(id:TopoKey) -> StateAccess<T> {
35 StateAccess {
36 id,
37 _phantom_data: PhantomData,
38 }
39 }
40
41 pub fn set(self, value: T) {
43 set_state_with_topo_id(value, self.id);
44 }
45
46 pub fn remove(self) -> Option<T> {
47 remove_state_with_topo_id(self.id)
48 }
49
50 pub fn delete(self) {
51 self.remove();
52 }
53
54 pub fn reset_on_unmount(self) -> Self {
55 on_unmount(move || self.delete());
56 self
57 }
58
59 pub fn update<F: FnOnce(&mut T) -> ()>(self, func: F) {
62 update_state_with_topo_id(self.id, func);
63 }
64
65 pub fn state_exists(self) -> bool {
66 state_exists_for_topo_id::<T>(self.id)
67 }
68
69 pub fn get_with<F: FnOnce(&T) -> R, R>(self, func: F) -> R {
70 read_state_with_topo_id(self.id, func)
71 }
72}
73
74pub trait CloneState<T>
75where
76 T: Clone + 'static,
77{
78 fn get(&self) -> T;
79
80 fn soft_get(&self) -> Option<T>;
81}
82
83impl<T> CloneState<T> for StateAccess<T>
84where
85 T: Clone + 'static,
86{
87 fn get(&self) -> T {
89 clone_state_with_topo_id::<T>(self.id).expect("state should be present")
90 }
91
92 fn soft_get(&self) -> Option<T> {
93 clone_state_with_topo_id::<T>(self.id)
94 }
95}
96
97#[derive(Clone)]
98struct ChangedWrapper<T>(T);
99
100pub trait ChangedState {
101 fn changed(&self) -> bool;
102}
103
104impl<T> ChangedState for StateAccess<T>
105where
106 T: Clone + 'static + PartialEq,
107{
108 fn changed(&self) -> bool {
109 if let Some(old_state) = clone_state_with_topo_id::<ChangedWrapper<T>>(self.id) {
110 old_state.0 != self.get()
111 } else {
112 set_state_with_topo_id(ChangedWrapper(self.get()), self.id);
113 true
114 }
115 }
116}
117
118impl<T> std::fmt::Display for StateAccess<T>
119where
120 T: std::fmt::Display + 'static,
121{
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 write!(f, "{}", self.get_with(|t| format!("{}", t)))
124 }
125}
126
127use std::ops::Add;
128use std::ops::Div;
129use std::ops::Mul;
130use std::ops::Sub;
131
132impl<T> Add for StateAccess<T>
133where
134 T: Copy + Add<Output = T> + 'static,
135{
136 type Output = T;
137
138 fn add(self, other: Self) -> Self::Output {
139 self.get_with(|s| other.get_with(|o| *o + *s))
140 }
141}
142
143impl<T> Mul for StateAccess<T>
144where
145 T: Copy + Mul<Output = T> + 'static,
146{
147 type Output = T;
148
149 fn mul(self, other: Self) -> Self::Output {
150 self.get_with(|s| other.get_with(|o| *o * *s))
151 }
152}
153
154impl<T> Div for StateAccess<T>
155where
156 T: Copy + Div<Output = T> + 'static,
157{
158 type Output = T;
159
160 fn div(self, other: Self) -> Self::Output {
161 self.get_with(|s| other.get_with(|o| *o / *s))
162 }
163}
164
165impl<T> Sub for StateAccess<T>
166where
167 T: Copy + Sub<Output = T> + 'static,
168{
169 type Output = T;
170
171 fn sub(self, other: Self) -> Self::Output {
172 self.get_with(|s| other.get_with(|o| *o - *s))
173 }
174}