1use super::{SharedStateError, SharedStorage, SharedValue, WrongStateError};
2use crate::{
3 InnerInference, SMut, SRef, State, StateMachineImpl, StateStorage, StateTrait,
4 StateUnionRuntime, StateUnionState, Transition, TransitionCallsite,
5 state_trait::{self, ErasedState},
6};
7use core::marker::PhantomData;
8use core::ops::{Deref, DerefMut};
9
10pub struct StateRef<G, T, S> {
26 guard: G,
27 marker: PhantomData<fn() -> (T, S)>,
28}
29
30impl<G, T, S> StateRef<G, T, S>
31where
32 G: Deref<Target = SharedValue<T>>,
33 S: SharedBorrowState,
34{
35 pub(super) fn from_guard<StorageError>(
36 guard: G,
37 ) -> Result<Self, SharedStateError<StorageError>> {
38 S::ensure_state(&guard.state)?;
39 Ok(Self {
40 guard,
41 marker: PhantomData,
42 })
43 }
44}
45
46impl<G, T, S> Deref for StateRef<G, T, S>
47where
48 G: Deref<Target = SharedValue<T>>,
49{
50 type Target = T;
51
52 fn deref(&self) -> &Self::Target {
53 &self.guard.value
54 }
55}
56
57pub struct StorageStateRef<'a, Backend>(PhantomData<&'a Backend>);
66
67impl<'a, Backend> StateStorage for StorageStateRef<'a, Backend>
68where
69 Backend: SharedStorage + 'a,
70{
71 type Inference = InnerInference;
72
73 type Inner<T, S>
74 = StateRef<Backend::ReadGuard<'a, T>, T, S>
75 where
76 T: StateMachineImpl;
77 type Machine<T>
78 = T
79 where
80 T: StateMachineImpl;
81
82 fn retag<T, From, To>(inner: Self::Inner<T, From>) -> Self::Inner<T, To>
83 where
84 T: StateMachineImpl,
85 {
86 StateRef {
87 guard: inner.guard,
88 marker: PhantomData,
89 }
90 }
91
92 fn complete_transition<T, From, To, Args>(
93 _state: State<Self, T, From>,
94 _args: Args,
95 _callsite: TransitionCallsite,
96 ) -> State<Self, T, To>
97 where
98 T: StateMachineImpl,
99 From: StateTrait,
100 To: crate::ConcreteStateTrait,
101 T::Standin: Transition<From, To>,
102 <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
103 {
104 panic!("immutable shared-state views cannot transition")
105 }
106
107 fn complete_transition_after_effect<T, From, To>(
108 _state: State<Self, T, From>,
109 _callsite: TransitionCallsite,
110 ) -> State<Self, T, To>
111 where
112 T: StateMachineImpl,
113 From: StateTrait,
114 To: crate::ConcreteStateTrait,
115 {
116 panic!("immutable shared-state views cannot transition")
117 }
118
119 fn inferred_state<T, S>(inner: &Self::Inner<T, S>) -> ErasedState
120 where
121 T: StateMachineImpl,
122 S: StateTrait,
123 {
124 state_trait::clone_erased(&inner.guard.state)
125 }
126}
127
128impl<'a, Backend> SRef for StorageStateRef<'a, Backend>
129where
130 Backend: SharedStorage + 'a,
131{
132 fn s_ref<T, S>(inner: &Self::Inner<T, S>) -> &T
133 where
134 T: StateMachineImpl,
135 {
136 inner
137 }
138}
139
140pub struct StateMut<G, T, S>
164where
165 G: DerefMut<Target = SharedValue<T>>,
166{
167 guard: Option<G>,
168 pending: ErasedState,
169 marker: PhantomData<fn() -> (T, S)>,
170}
171
172pub struct StorageStateMut<'a, Backend>(PhantomData<&'a Backend>);
174
175impl<'a, Backend> StateStorage for StorageStateMut<'a, Backend>
176where
177 Backend: SharedStorage + 'a,
178{
179 type Inference = InnerInference;
180
181 type Inner<T, S>
182 = StateMut<Backend::WriteGuard<'a, T>, T, S>
183 where
184 T: StateMachineImpl;
185 type Machine<T>
186 = T
187 where
188 T: StateMachineImpl;
189
190 fn retag<T, From, To>(mut inner: Self::Inner<T, From>) -> Self::Inner<T, To>
191 where
192 T: StateMachineImpl,
193 {
194 StateMut {
195 guard: inner.guard.take(),
196 pending: state_trait::clone_erased(&inner.pending),
197 marker: PhantomData,
198 }
199 }
200
201 fn complete_transition<T, From, To, Args>(
202 mut state: State<Self, T, From>,
203 _args: Args,
204 _callsite: TransitionCallsite,
205 ) -> State<Self, T, To>
206 where
207 T: StateMachineImpl,
208 From: StateTrait,
209 To: crate::ConcreteStateTrait,
210 T::Standin: Transition<From, To>,
211 <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
212 {
213 State {
214 inner: StateMut {
215 guard: state.inner.guard.take(),
216 pending: state_trait::erased_state::<To>(),
217 marker: PhantomData,
218 },
219 marker: PhantomData,
220 }
221 }
222
223 fn complete_transition_after_effect<T, From, To>(
224 mut state: State<Self, T, From>,
225 _callsite: TransitionCallsite,
226 ) -> State<Self, T, To>
227 where
228 T: StateMachineImpl,
229 From: StateTrait,
230 To: crate::ConcreteStateTrait,
231 {
232 State {
233 inner: StateMut {
234 guard: state.inner.guard.take(),
235 pending: state_trait::erased_state::<To>(),
236 marker: PhantomData,
237 },
238 marker: PhantomData,
239 }
240 }
241
242 fn inferred_state<T, S>(inner: &Self::Inner<T, S>) -> ErasedState
243 where
244 T: StateMachineImpl,
245 S: StateTrait,
246 {
247 state_trait::clone_erased(&inner.pending)
248 }
249}
250
251impl<'a, Backend> SRef for StorageStateMut<'a, Backend>
252where
253 Backend: SharedStorage + 'a,
254{
255 fn s_ref<T, S>(inner: &Self::Inner<T, S>) -> &T
256 where
257 T: StateMachineImpl,
258 {
259 inner
260 }
261}
262
263impl<'a, Backend> SMut for StorageStateMut<'a, Backend>
264where
265 Backend: SharedStorage + 'a,
266{
267 fn s_mut<T, S>(inner: &mut Self::Inner<T, S>) -> &mut T
268 where
269 T: StateMachineImpl,
270 {
271 inner
272 }
273}
274
275impl<G, T, S> StateMut<G, T, S>
276where
277 G: DerefMut<Target = SharedValue<T>>,
278 S: SharedBorrowState,
279{
280 pub(super) fn from_guard<StorageError>(
281 guard: G,
282 ) -> Result<Self, SharedStateError<StorageError>> {
283 S::ensure_state(&guard.state)?;
284 let pending = S::initial_pending(&guard.state);
285 Ok(Self {
286 guard: Some(guard),
287 pending,
288 marker: PhantomData,
289 })
290 }
291}
292
293#[must_use]
297pub fn transition_mut<G, T, S, Next>(
298 state: StateMut<G, T, S>,
299 _token: T::TransitionToken,
300) -> StateMutTransitionCall<G, T, S, Next>
301where
302 G: DerefMut<Target = SharedValue<T>>,
303 T: StateMachineImpl,
304 T::Standin: Transition<S, Next>,
305{
306 StateMutTransitionCall {
307 state,
308 to: PhantomData,
309 }
310}
311
312impl<G, T, S> Deref for StateMut<G, T, S>
313where
314 G: DerefMut<Target = SharedValue<T>>,
315{
316 type Target = T;
317
318 fn deref(&self) -> &Self::Target {
319 &self.guard.as_ref().expect("guard is present").value
320 }
321}
322
323impl<G, T, S> DerefMut for StateMut<G, T, S>
324where
325 G: DerefMut<Target = SharedValue<T>>,
326{
327 fn deref_mut(&mut self) -> &mut Self::Target {
328 &mut self.guard.as_mut().expect("guard is present").value
329 }
330}
331
332impl<G, T, S> Drop for StateMut<G, T, S>
333where
334 G: DerefMut<Target = SharedValue<T>>,
335{
336 fn drop(&mut self) {
337 if let Some(guard) = self.guard.as_mut() {
338 guard.state = state_trait::clone_erased(&self.pending);
339 }
340 }
341}
342
343#[doc(hidden)]
345pub struct StateMutTransitionCall<G, T, From, To>
346where
347 G: DerefMut<Target = SharedValue<T>>,
348{
349 state: StateMut<G, T, From>,
350 to: PhantomData<fn() -> To>,
351}
352
353impl<G, T, From, To> StateMutTransitionCall<G, T, From, To>
354where
355 G: DerefMut<Target = SharedValue<T>>,
356{
357 pub fn call<Args>(mut self, _args: Args) -> StateMut<G, T, To>
358 where
359 T: StateMachineImpl,
360 T::Standin: Transition<From, To>,
361 <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
362 To: crate::ConcreteStateTrait,
363 {
364 StateMut {
365 guard: self.state.guard.take(),
366 pending: state_trait::erased_state::<To>(),
367 marker: PhantomData,
368 }
369 }
370}
371
372#[doc(hidden)]
374pub trait SharedBorrowState: StateTrait {
375 fn ensure_state(actual: &ErasedState) -> Result<(), WrongStateError>;
376 fn initial_pending(actual: &ErasedState) -> ErasedState;
377}
378
379pub auto trait ExactSharedBorrowState {}
380
381impl<Marker> !ExactSharedBorrowState for StateUnionState<Marker> {}
382
383impl<S> SharedBorrowState for S
384where
385 S: crate::ConcreteStateTrait + ExactSharedBorrowState,
386{
387 fn ensure_state(actual: &ErasedState) -> Result<(), WrongStateError> {
388 if state_trait::is_state::<S>(actual) {
389 Ok(())
390 } else {
391 Err(WrongStateError {
392 expected: core::any::type_name::<S>(),
393 actual: actual.type_name(),
394 })
395 }
396 }
397
398 fn initial_pending(_actual: &ErasedState) -> ErasedState {
399 state_trait::erased_state::<S>()
400 }
401}
402
403impl<Marker> SharedBorrowState for StateUnionState<Marker>
404where
405 Marker: StateUnionRuntime + 'static,
406 StateUnionState<Marker>: StateTrait,
407{
408 fn ensure_state(actual: &ErasedState) -> Result<(), WrongStateError> {
409 if Marker::contains(&**actual) {
410 Ok(())
411 } else {
412 Err(WrongStateError {
413 expected: Marker::expected_type_name(),
414 actual: actual.type_name(),
415 })
416 }
417 }
418
419 fn initial_pending(actual: &ErasedState) -> ErasedState {
420 state_trait::clone_erased(actual)
421 }
422}