1use std::sync::OnceLock;
2
3use crate::{
4 ActionId, ActionMeta, ActionWithMeta, AnyAction, Callback, Dispatcher, Effects,
5 EnablingCondition, Instant, Reducer, SubStore, SystemTime, TimeService, Timestamp,
6};
7
8pub struct StateWrapper<State> {
13 inner: State,
14}
15
16impl<State> StateWrapper<State> {
17 #[inline(always)]
19 pub fn get(&self) -> &State {
20 &self.inner
21 }
22
23 #[inline(always)]
28 fn get_mut(&mut self) -> &mut State {
29 &mut self.inner
30 }
31}
32
33impl<T: Clone> Clone for StateWrapper<T> {
34 fn clone(&self) -> Self {
35 Self {
36 inner: self.inner.clone(),
37 }
38 }
39}
40
41static INITIAL_TIME: OnceLock<(Instant, SystemTime)> = OnceLock::new();
43
44pub fn monotonic_to_time(time: Option<Instant>) -> u64 {
48 let (monotonic, system) = INITIAL_TIME.get_or_init(|| (Instant::now(), SystemTime::now()));
49 let time_passed = time.unwrap_or_else(Instant::now).duration_since(*monotonic);
50 system
51 .duration_since(SystemTime::UNIX_EPOCH)
52 .map(|x| x + time_passed)
53 .map(|x| x.as_nanos())
54 .unwrap_or(0) as u64
55}
56
57pub struct Store<State, Service, Action> {
64 reducer: Reducer<State, Action>,
65 effects: Effects<State, Service, Action>,
66
67 pub state: StateWrapper<State>,
72 pub service: Service,
73
74 initial_monotonic_time: Instant,
75 initial_time: Timestamp,
76
77 recursion_depth: u32,
79
80 last_action_id: ActionId,
81}
82
83impl<State, Service, Action> Store<State, Service, Action>
84where
85 Service: TimeService,
86 Action: EnablingCondition<State>,
87{
88 pub fn new(
90 reducer: Reducer<State, Action>,
91 effects: Effects<State, Service, Action>,
92 mut service: Service,
93 initial_time: SystemTime,
94 initial_state: State,
95 ) -> Self {
96 let initial_monotonic_time = service.monotonic_time();
97 let initial_time_nanos = initial_time
98 .duration_since(SystemTime::UNIX_EPOCH)
99 .map(|x| x.as_nanos())
100 .unwrap_or(0);
101
102 INITIAL_TIME.get_or_init(move || (initial_monotonic_time, initial_time));
103
104 Self {
105 reducer,
106 effects,
107 service,
108 state: StateWrapper {
109 inner: initial_state,
110 },
111
112 initial_monotonic_time,
113 initial_time: Timestamp::new(initial_time_nanos as u64),
114
115 recursion_depth: 0,
116 last_action_id: ActionId::new_unchecked(initial_time_nanos as u64),
117 }
118 }
119
120 #[inline(always)]
122 pub fn state(&self) -> &State {
123 self.state.get()
124 }
125
126 #[inline(always)]
127 pub fn service(&mut self) -> &mut Service {
128 &mut self.service
129 }
130
131 pub fn monotonic_to_time(&self, monotonic_time: Instant) -> u64 {
133 monotonic_to_time(Some(monotonic_time))
134 }
135
136 pub fn dispatch<T>(&mut self, action: T) -> bool
143 where
144 T: Into<Action> + EnablingCondition<State>,
145 {
146 if !action.is_enabled(self.state(), self.last_action_id.into()) {
147 return false;
148 }
149 self.dispatch_enabled(action.into());
150
151 true
152 }
153
154 pub fn dispatch_callback<T>(&mut self, callback: Callback<T>, args: T) -> bool
155 where
156 T: 'static,
157 Action: From<AnyAction> + EnablingCondition<State>,
158 {
159 let action: Action = callback.call(args);
160 self.dispatch(action)
161 }
162
163 pub fn sub_dispatch<A, S>(&mut self, action: A) -> bool
170 where
171 A: Into<<Self as SubStore<State, S>>::SubAction> + EnablingCondition<S>,
172 <Self as SubStore<State, S>>::SubAction: Into<Action>,
173 Self: SubStore<State, S>,
174 {
175 if !action.is_enabled(
176 <Self as SubStore<State, S>>::state(self),
177 self.last_action_id.into(),
178 ) {
179 return false;
180 }
181 self.dispatch_enabled(action.into().into());
182
183 true
184 }
185
186 fn update_action_id(&mut self) -> ActionId {
187 let prev_action_id = self.last_action_id;
188 let now = self.initial_time
189 + self
190 .service
191 .monotonic_time()
192 .duration_since(self.initial_monotonic_time);
193
194 let t = (Timestamp::from(prev_action_id) + 1).max(now);
195 self.last_action_id = ActionId::new_unchecked(t.into());
196 prev_action_id
197 }
198
199 fn dispatch_enabled(&mut self, action: Action) {
201 let prev = self.update_action_id();
202 self.recursion_depth += 1;
203
204 let action_with_meta =
205 ActionMeta::new(self.last_action_id, prev, self.recursion_depth).with_action(action);
206
207 let mut dispatcher = Dispatcher::new();
208 self.dispatch_reducer(&action_with_meta, &mut dispatcher);
209 self.dispatch_effects(action_with_meta, dispatcher);
210
211 self.recursion_depth -= 1;
212 }
213
214 #[inline(always)]
216 fn dispatch_reducer(
217 &mut self,
218 action_with_id: &ActionWithMeta<Action>,
219 dispatcher: &mut Dispatcher<Action, State>,
220 ) {
221 (self.reducer)(self.state.get_mut(), action_with_id, dispatcher);
222 }
223
224 #[inline(always)]
226 fn dispatch_effects(
227 &mut self,
228 action_with_id: ActionWithMeta<Action>,
229 mut queued: Dispatcher<Action, State>,
230 ) {
231 (self.effects)(self, action_with_id);
233
234 while let Some(action) = queued.pop() {
236 if action.is_enabled(self.state(), self.last_action_id.into()) {
237 self.dispatch_enabled(action);
238 }
239 }
240 }
241}
242
243impl<State, Service, Action> Clone for Store<State, Service, Action>
244where
245 State: Clone,
246 Service: Clone,
247 Action: Clone + EnablingCondition<State>,
248{
249 fn clone(&self) -> Self {
250 Self {
251 reducer: self.reducer,
252 effects: self.effects,
253 service: self.service.clone(),
254 state: self.state.clone(),
255
256 initial_monotonic_time: self.initial_monotonic_time,
257 initial_time: self.initial_time,
258
259 recursion_depth: self.recursion_depth,
260 last_action_id: self.last_action_id,
261 }
262 }
263}