Skip to main content

magicstatemachines/state/storage/
owned.rs

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