Skip to main content

magicstatemachines/state/storage/
owned.rs

1use super::{
2    MayTransition, SMapRuntime, SMove, SMut, SPinMut, SPinRef, SRef, State, StateStorage,
3    StateStorageNew, TransitionCallsite,
4};
5use crate::state::owned::{StateOwned, complete_transition};
6use crate::{Initial, StateMachineImpl, Transition};
7use core::marker::PhantomData;
8use core::pin::Pin;
9#[cfg(feature = "unique-rc-arc")]
10use std::rc::UniqueRc;
11#[cfg(feature = "unique-rc-arc")]
12use std::sync::UniqueArc;
13
14/// Backend for directly owned values.
15pub struct StorageStateOwned;
16
17/// Short alias for [`StorageStateOwned`].
18pub type SOwned = StorageStateOwned;
19
20/// Backend for `Box<T>` owned values.
21pub struct StorageStateOwnedBox;
22
23/// Backend for `Pin<Box<T>>` owned values.
24pub struct StorageStateOwnedPinBox;
25
26/// Backend for `UniqueRc<T>` owned values.
27#[cfg(feature = "unique-rc-arc")]
28pub struct StorageStateOwnedUniqueRc;
29
30/// Backend for `UniqueArc<T>` owned values.
31#[cfg(feature = "unique-rc-arc")]
32pub struct StorageStateOwnedUniqueArc;
33
34impl StateStorage for StorageStateOwned {
35    type Inner<T, S>
36        = StateOwned<T, S>
37    where
38        T: StateMachineImpl;
39    type Machine<T>
40        = T
41    where
42        T: StateMachineImpl;
43
44    fn retag<T, From, To>(inner: Self::Inner<T, From>) -> Self::Inner<T, To>
45    where
46        T: StateMachineImpl,
47    {
48        super::retag_owned(inner)
49    }
50}
51
52impl MayTransition for StorageStateOwned {
53    fn complete_transition<T, From, To, Args>(
54        state: State<Self, T, From>,
55        _args: Args,
56        callsite: TransitionCallsite,
57    ) -> State<Self, T, To>
58    where
59        T: StateMachineImpl,
60        From: crate::StateTrait,
61        To: crate::ConcreteStateTrait,
62        T::Standin: Transition<From, To>,
63        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
64    {
65        State {
66            inner: complete_transition(state.inner, callsite),
67            marker: PhantomData,
68        }
69    }
70
71    fn complete_transition_after_effect<T, From, To>(
72        state: State<Self, T, From>,
73        callsite: TransitionCallsite,
74    ) -> State<Self, T, To>
75    where
76        T: StateMachineImpl,
77        From: crate::StateTrait,
78        To: crate::ConcreteStateTrait,
79    {
80        State {
81            inner: complete_transition(state.inner, callsite),
82            marker: PhantomData,
83        }
84    }
85}
86
87impl StateStorageNew for StorageStateOwned {
88    fn new<T, S>(value: T) -> Self::Inner<T, S>
89    where
90        T: StateMachineImpl,
91        T::Standin: Initial<S>,
92    {
93        StateOwned::new(value)
94    }
95}
96
97impl SRef for StorageStateOwned {
98    fn s_ref<T, S>(inner: &Self::Inner<T, S>) -> &T
99    where
100        T: StateMachineImpl,
101    {
102        &inner.value
103    }
104}
105
106impl SMut for StorageStateOwned {
107    fn s_mut<T, S>(inner: &mut Self::Inner<T, S>) -> &mut T
108    where
109        T: StateMachineImpl,
110    {
111        &mut inner.value
112    }
113}
114
115impl SMove for StorageStateOwned {}
116
117impl<FromRuntime, ToRuntime> SMapRuntime<FromRuntime, ToRuntime> for StorageStateOwned
118where
119    FromRuntime: StateMachineImpl,
120    ToRuntime: StateMachineImpl,
121{
122    fn map_runtime<S, F>(state: State<Self, FromRuntime, S>, f: F) -> State<Self, ToRuntime, S>
123    where
124        F: FnOnce(FromRuntime) -> ToRuntime,
125    {
126        State {
127            inner: StateOwned {
128                value: f(state.inner.value),
129                state: PhantomData,
130                #[cfg(feature = "tracing")]
131                trace: state.inner.trace,
132            },
133            marker: PhantomData,
134        }
135    }
136}
137
138macro_rules! indirect_owned_storage {
139    ($storage:ty, $wrapper:ident) => {
140        impl StateStorage for $storage {
141            type Inner<T, S>
142                = StateOwned<$wrapper<T>, S>
143            where
144                T: StateMachineImpl;
145            type Machine<T>
146                = $wrapper<T>
147            where
148                T: StateMachineImpl;
149
150            fn retag<T, From, To>(inner: Self::Inner<T, From>) -> Self::Inner<T, To>
151            where
152                T: StateMachineImpl,
153            {
154                super::retag_owned(inner)
155            }
156        }
157
158        impl MayTransition for $storage {
159            fn complete_transition<T, From, To, Args>(
160                state: State<Self, T, From>,
161                _args: Args,
162                callsite: TransitionCallsite,
163            ) -> State<Self, T, To>
164            where
165                T: StateMachineImpl,
166                From: crate::StateTrait,
167                To: crate::ConcreteStateTrait,
168                T::Standin: Transition<From, To>,
169                <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
170            {
171                State {
172                    inner: complete_transition(state.inner, callsite),
173                    marker: PhantomData,
174                }
175            }
176
177            fn complete_transition_after_effect<T, From, To>(
178                state: State<Self, T, From>,
179                callsite: TransitionCallsite,
180            ) -> State<Self, T, To>
181            where
182                T: StateMachineImpl,
183                From: crate::StateTrait,
184                To: crate::ConcreteStateTrait,
185            {
186                State {
187                    inner: complete_transition(state.inner, callsite),
188                    marker: PhantomData,
189                }
190            }
191        }
192
193        impl StateStorageNew for $storage {
194            fn new<T, S>(value: T) -> Self::Inner<T, S>
195            where
196                T: StateMachineImpl,
197                <Self::Machine<T> as StateMachineImpl>::Standin: Initial<S>,
198            {
199                StateOwned::new($wrapper::new(value))
200            }
201        }
202
203        impl SRef for $storage {
204            fn s_ref<T, S>(inner: &Self::Inner<T, S>) -> &T
205            where
206                T: StateMachineImpl,
207            {
208                &inner.value
209            }
210        }
211
212        impl SMut for $storage {
213            fn s_mut<T, S>(inner: &mut Self::Inner<T, S>) -> &mut T
214            where
215                T: StateMachineImpl,
216            {
217                &mut inner.value
218            }
219        }
220
221        impl SMove for $storage {}
222    };
223
224    ($storage:ty, $wrapper:ident, $map:path) => {
225        indirect_owned_storage!($storage, $wrapper);
226        impl<FromRuntime, ToRuntime> SMapRuntime<FromRuntime, ToRuntime> for $storage
227        where
228            FromRuntime: StateMachineImpl,
229            ToRuntime: StateMachineImpl,
230        {
231            fn map_runtime<S, F>(
232                state: State<Self, FromRuntime, S>,
233                f: F,
234            ) -> State<Self, ToRuntime, S>
235            where
236                F: FnOnce(FromRuntime) -> ToRuntime,
237            {
238                State {
239                    inner: StateOwned {
240                        value: $map(state.inner.value, f),
241                        state: PhantomData,
242                        #[cfg(feature = "tracing")]
243                        trace: state.inner.trace,
244                    },
245                    marker: PhantomData,
246                }
247            }
248        }
249    };
250}
251
252fn map_box<FromRuntime, ToRuntime, F>(value: Box<FromRuntime>, f: F) -> Box<ToRuntime>
253where
254    F: FnOnce(FromRuntime) -> ToRuntime,
255{
256    Box::new(f(*value))
257}
258
259indirect_owned_storage!(StorageStateOwnedBox, Box, map_box);
260
261#[cfg(feature = "unique-rc-arc")]
262indirect_owned_storage!(StorageStateOwnedUniqueRc, UniqueRc);
263#[cfg(feature = "unique-rc-arc")]
264indirect_owned_storage!(StorageStateOwnedUniqueArc, UniqueArc);
265
266impl StateStorage for StorageStateOwnedPinBox {
267    type Inner<T, S>
268        = StateOwned<Pin<Box<T>>, S>
269    where
270        T: StateMachineImpl;
271    type Machine<T>
272        = Pin<Box<T>>
273    where
274        T: StateMachineImpl;
275
276    fn retag<T, From, To>(inner: Self::Inner<T, From>) -> Self::Inner<T, To>
277    where
278        T: StateMachineImpl,
279    {
280        super::retag_owned(inner)
281    }
282}
283
284impl MayTransition for StorageStateOwnedPinBox {
285    fn complete_transition<T, From, To, Args>(
286        state: State<Self, T, From>,
287        _args: Args,
288        callsite: TransitionCallsite,
289    ) -> State<Self, T, To>
290    where
291        T: StateMachineImpl,
292        From: crate::StateTrait,
293        To: crate::ConcreteStateTrait,
294        T::Standin: Transition<From, To>,
295        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
296    {
297        State {
298            inner: complete_transition(state.inner, callsite),
299            marker: PhantomData,
300        }
301    }
302
303    fn complete_transition_after_effect<T, From, To>(
304        state: State<Self, T, From>,
305        callsite: TransitionCallsite,
306    ) -> State<Self, T, To>
307    where
308        T: StateMachineImpl,
309        From: crate::StateTrait,
310        To: crate::ConcreteStateTrait,
311    {
312        State {
313            inner: complete_transition(state.inner, callsite),
314            marker: PhantomData,
315        }
316    }
317}
318
319impl StateStorageNew for StorageStateOwnedPinBox {
320    fn new<T, S>(value: T) -> Self::Inner<T, S>
321    where
322        T: StateMachineImpl,
323        <Self::Machine<T> as StateMachineImpl>::Standin: Initial<S>,
324    {
325        StateOwned::new(Box::pin(value))
326    }
327}
328
329impl SRef for StorageStateOwnedPinBox {
330    fn s_ref<T, S>(inner: &Self::Inner<T, S>) -> &T
331    where
332        T: StateMachineImpl,
333    {
334        &inner.value
335    }
336}
337
338impl SPinRef for StorageStateOwnedPinBox {
339    fn s_pin_ref<T, S>(inner: &Self::Inner<T, S>) -> Pin<&T>
340    where
341        T: StateMachineImpl,
342    {
343        inner.value.as_ref()
344    }
345}
346
347impl SPinMut for StorageStateOwnedPinBox {
348    fn s_pin_mut<T, S>(inner: &mut Self::Inner<T, S>) -> Pin<&mut T>
349    where
350        T: StateMachineImpl,
351    {
352        inner.value.as_mut()
353    }
354}
355
356impl SMove for StorageStateOwnedPinBox {}
357
358impl<FromRuntime, ToRuntime> SMapRuntime<FromRuntime, ToRuntime> for StorageStateOwnedPinBox
359where
360    FromRuntime: StateMachineImpl + Unpin,
361    ToRuntime: StateMachineImpl,
362{
363    fn map_runtime<S, F>(state: State<Self, FromRuntime, S>, f: F) -> State<Self, ToRuntime, S>
364    where
365        F: FnOnce(FromRuntime) -> ToRuntime,
366    {
367        State {
368            inner: StateOwned {
369                value: Box::pin(f(*Pin::into_inner(state.inner.value))),
370                state: PhantomData,
371                #[cfg(feature = "tracing")]
372                trace: state.inner.trace,
373            },
374            marker: PhantomData,
375        }
376    }
377}