Skip to main content

magicstatemachines/state/storage/
mod.rs

1mod owned;
2
3use crate::{
4    ConcreteStateKind, DiscriminatedState, Initial, StateConcreteProvenState,
5    StateConcreteTransitionProof, StateKind, StateMachineImpl, StateUnionDiscriminant,
6    StateUnionDiscriminatedTransition, StateUnionErased, StateUnionProofTarget,
7    StateUnionProvenState, StateUnionSharedEffect, StateUnionSharedTransitionEffect,
8    StateUnionTransitionProof, StateWithProof, Transition, UnionStateKind, state_trait,
9};
10use core::marker::PhantomData;
11use core::ops::{Deref, DerefMut};
12#[cfg(feature = "tracing")]
13use core::panic::Location;
14use core::pin::Pin;
15#[cfg(feature = "unique-rc-arc")]
16use std::rc::UniqueRc;
17#[cfg(feature = "unique-rc-arc")]
18use std::sync::UniqueArc;
19
20pub use owned::{SOwned, StorageStateOwned, StorageStateOwnedBox, StorageStateOwnedPinBox};
21#[cfg(feature = "unique-rc-arc")]
22pub use owned::{StorageStateOwnedUniqueArc, StorageStateOwnedUniqueRc};
23
24/// Owned state whose runtime value is stored in `Box<T>`.
25///
26/// This is only a type alias for `State<StorageStateOwnedBox, T, S>`. Create it
27/// from an already-owned state with [`SBox::new`](State<StorageStateOwnedBox, T, S>::new)
28/// so the current state is preserved while changing containers:
29///
30/// ```ignore
31/// let owned: State<SOwned, Connection, Disconnected> = State::new(connection);
32/// let boxed: SBox<Connection, Disconnected> = SBox::new(owned);
33/// ```
34pub type SBox<T, S> = State<StorageStateOwnedBox, T, S>;
35/// Owned state whose runtime value is stored in `Pin<Box<T>>`.
36///
37/// This is the pinned counterpart to [`SBox`]. Pinning consumes a boxed state
38/// rather than raw `T`, again preserving the already-proven current state.
39///
40/// Pinned storage is deliberately not just "boxed plus `SMut`". For
41/// `T: !Unpin`, the backend can expose [`Pin<&T>`](core::pin::Pin) and
42/// `Pin<&mut T>` through [`SPinRef`] and [`SPinMut`], but it does not expose
43/// `&mut T`. That means ordinary transitions requiring `S: SMut` stay
44/// unavailable, while pinned transition methods can still be written:
45///
46/// ```ignore
47/// impl Connection {
48///     fn connect<S>(self: State<S, Self, Disconnected>) -> State<S, Self, Connected>
49///     where
50///         S: magicstatemachines::SPinMut,
51///     {
52///         magicstatemachines::transition!(pin self)
53///     }
54/// }
55/// ```
56pub type SPinBox<T, S> = State<StorageStateOwnedPinBox, T, S>;
57
58fn retag_owned<T, From, To>(inner: crate::StateOwned<T, From>) -> crate::StateOwned<T, To> {
59    crate::StateOwned {
60        value: inner.value,
61        state: PhantomData,
62        #[cfg(feature = "tracing")]
63        trace: inner.trace,
64    }
65}
66
67type StateMarker<Storage, T, S> = PhantomData<fn() -> (Storage, T, S)>;
68type TransitionMarker<Storage, T, From, To> = PhantomData<fn() -> (Storage, T, From, To)>;
69
70/// Selects the implementation-side effect for a declared transition.
71#[doc(hidden)]
72pub trait TransitionEffectSelector<From, To>: StateMachineImpl {
73    type Effect;
74}
75
76/// Selects the pinned implementation-side effect for a declared transition.
77#[doc(hidden)]
78pub trait PinnedTransitionEffectSelector<From, To>: StateMachineImpl {
79    type Effect;
80}
81
82/// Applies implementation-side transition effects before the state is retagged.
83#[doc(hidden)]
84pub trait TransitionEffect<T, From, To, Args>
85where
86    T: StateMachineImpl,
87{
88    fn apply(value: &mut T, args: Args);
89}
90
91/// Applies implementation-side transition effects through pinned access.
92///
93/// This is the pinned counterpart to [`TransitionEffect`]. It is used by
94/// `pinned transition` entries in [`StateMachineImpl!`](macro@crate::StateMachineImpl)
95/// and by [`transition!(pin state, ...)`](macro@crate::transition). The effect
96/// receives `Pin<&mut T>`, so a `!Unpin` runtime can update interior fields or
97/// call pinned methods without ever exposing `&mut T`.
98#[doc(hidden)]
99pub trait PinnedTransitionEffect<T, From, To, Args>
100where
101    T: StateMachineImpl,
102{
103    fn apply(value: Pin<&mut T>, args: Args);
104}
105
106/// Selects where a storage backend's authoritative state marker is inferred.
107#[doc(hidden)]
108pub trait InferenceKind {
109    type Inference: StateInference;
110}
111
112/// State marker inference carried by discriminated storage.
113#[doc(hidden)]
114pub trait StateInference {
115    fn new<Storage, T, S>(inner: &Storage::Inner<T, S>) -> Self
116    where
117        Storage: StateStorage,
118        T: StateMachineImpl,
119        S: crate::ConcreteStateTrait;
120
121    fn from_erased(state: state_trait::ErasedState) -> Self;
122
123    fn state<Storage, T, S>(&self, inner: &Storage::Inner<T, S>) -> state_trait::ErasedState
124    where
125        Storage: StateStorage,
126        T: StateMachineImpl,
127        S: crate::StateTrait;
128}
129
130/// Inference stored outside the wrapped backend, used by type-only storage.
131#[doc(hidden)]
132pub struct OuterInference;
133
134/// Inference delegated to the wrapped backend, used by runtime-state storage.
135#[doc(hidden)]
136pub struct InnerInference;
137
138/// ZST inference value for [`InnerInference`].
139#[doc(hidden)]
140#[derive(Clone, Copy)]
141pub struct InnerStateInference;
142
143impl InferenceKind for OuterInference {
144    type Inference = state_trait::ErasedState;
145}
146
147impl InferenceKind for InnerInference {
148    type Inference = InnerStateInference;
149}
150
151impl StateInference for state_trait::ErasedState {
152    fn new<Storage, T, S>(_inner: &Storage::Inner<T, S>) -> Self
153    where
154        Storage: StateStorage,
155        T: StateMachineImpl,
156        S: crate::ConcreteStateTrait,
157    {
158        state_trait::erased_state::<S>()
159    }
160
161    fn from_erased(state: state_trait::ErasedState) -> Self {
162        state
163    }
164
165    fn state<Storage, T, S>(&self, _inner: &Storage::Inner<T, S>) -> state_trait::ErasedState
166    where
167        Storage: StateStorage,
168        T: StateMachineImpl,
169        S: crate::StateTrait,
170    {
171        state_trait::clone_erased(self)
172    }
173}
174
175impl StateInference for InnerStateInference {
176    fn new<Storage, T, S>(_inner: &Storage::Inner<T, S>) -> Self
177    where
178        Storage: StateStorage,
179        T: StateMachineImpl,
180        S: crate::ConcreteStateTrait,
181    {
182        Self
183    }
184
185    fn from_erased(_state: state_trait::ErasedState) -> Self {
186        Self
187    }
188
189    fn state<Storage, T, S>(&self, inner: &Storage::Inner<T, S>) -> state_trait::ErasedState
190    where
191        Storage: StateStorage,
192        T: StateMachineImpl,
193        S: crate::StateTrait,
194    {
195        Storage::inferred_state(inner)
196    }
197}
198
199/// Storage backend used by [`State`].
200///
201/// `State<Storage, T, S>` is only a typed view; the actual representation is
202/// selected by this trait. The same implementation methods can therefore work
203/// for directly owned values, boxed values, pinned values, shared guard views,
204/// and discriminated union views as long as they ask for the right capability
205/// bound.
206///
207/// Backend authors provide an `Inner<T, S>` generic associated type. The
208/// library retags that `Inner` after a successful transition, so the backend
209/// controls where data is stored while the state-machine contract still
210/// controls which retags are legal.
211///
212/// Most users do not implement this trait. They choose one of the built-in
213/// storage aliases and write bounds on methods:
214///
215/// ```ignore
216/// use magicstatemachines::{SRef, SMut, State, transition};
217/// use test_def::{InOnline, Online};
218/// use test_def::states::{Authenticated, Connected};
219///
220/// impl Connection {
221///     fn endpoint<S>(self: &State<S, Self, impl InOnline>) -> &str
222///     where
223///         S: SRef,
224///     {
225///         &self.endpoint
226///     }
227///
228///     fn authenticate<S>(
229///         self: State<S, Self, Connected>,
230///         user: String,
231///     ) -> State<S, Self, Authenticated>
232///     where
233///         S: SMut,
234///     {
235///         transition!(self, user)
236///     }
237/// }
238/// ```
239pub trait StateStorage: Sized {
240    /// Selects how [`SDiscriminated`](crate::SDiscriminated) recovers the current state marker.
241    type Inference: InferenceKind = OuterInference;
242
243    /// Concrete state representation used by this storage backend.
244    type Inner<T, S>
245    where
246        T: StateMachineImpl;
247
248    /// Type that carries the state-machine implementation contract.
249    type Machine<T>: StateMachineImpl<Standin = T::Standin, Impl = T::Impl, TransitionToken = T::TransitionToken>
250    where
251        T: StateMachineImpl;
252
253    #[doc(hidden)]
254    fn retag<T, From, To>(inner: Self::Inner<T, From>) -> Self::Inner<T, To>
255    where
256        T: StateMachineImpl;
257
258    /// Retags a state after checking that `Args` matches the declared transition signature.
259    ///
260    /// Storage backends normally delegate this to their inner representation.
261    /// Implementation crates should call transitions through [`transition!`](macro@crate::transition)
262    /// rather than invoking this method directly.
263    fn complete_transition<T, From, To, Args>(
264        state: State<Self, T, From>,
265        args: Args,
266        callsite: TransitionCallsite,
267    ) -> State<Self, T, To>
268    where
269        T: StateMachineImpl,
270        From: crate::StateTrait,
271        To: crate::ConcreteStateTrait,
272        T::Standin: Transition<From, To>,
273        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>;
274
275    #[doc(hidden)]
276    fn complete_transition_after_effect<T, From, To>(
277        state: State<Self, T, From>,
278        callsite: TransitionCallsite,
279    ) -> State<Self, T, To>
280    where
281        T: StateMachineImpl,
282        From: crate::StateTrait,
283        To: crate::ConcreteStateTrait;
284
285    #[doc(hidden)]
286    fn inferred_state<T, State>(inner: &Self::Inner<T, State>) -> state_trait::ErasedState
287    where
288        T: StateMachineImpl,
289        State: crate::StateTrait,
290    {
291        let _ = inner;
292        state_trait::static_erased_state::<State>()
293    }
294}
295
296#[doc(hidden)]
297pub fn complete_transition_after_effect<Storage, T, From, To>(
298    state: State<Storage, T, From>,
299    callsite: TransitionCallsite,
300) -> State<Storage, T, To>
301where
302    Storage: StateStorage,
303    T: StateMachineImpl,
304    From: crate::StateTrait,
305    To: crate::ConcreteStateTrait,
306{
307    Storage::complete_transition_after_effect(state, callsite)
308}
309
310/// Storage backend that can create initial owned state.
311///
312/// This is the capability behind [`State::new`]. The `Initial` bound prevents
313/// raw runtime data from being introduced in a non-initial state.
314pub trait StateStorageNew: StateStorage {
315    /// Creates a backend-specific inner value in an allowed initial state.
316    fn new<T, State>(value: T) -> Self::Inner<T, State>
317    where
318        T: StateMachineImpl,
319        <Self::Machine<T> as StateMachineImpl>::Standin: Initial<State>;
320}
321
322/// Storage backend that can expose a runtime reference.
323///
324/// Use `S: SRef` for methods that only read the runtime implementation. This
325/// bound covers owned states, boxed/pinned states, and read or write guards
326/// from shared storage.
327pub trait SRef: StateStorage {
328    /// Borrows the runtime implementation from this storage backend.
329    fn s_ref<T, State>(inner: &Self::Inner<T, State>) -> &T
330    where
331        T: StateMachineImpl;
332}
333
334/// Storage backend that can expose a mutable runtime reference.
335///
336/// Use `S: SMut` for methods that mutate runtime data or call
337/// [`transition!`](macro@crate::transition). Transition effect bodies always
338/// receive `&mut T`, so a transition method normally needs this bound even if
339/// the body is empty.
340pub trait SMut: SRef {
341    /// Mutably borrows the runtime implementation from this storage backend.
342    fn s_mut<T, State>(inner: &mut Self::Inner<T, State>) -> &mut T
343    where
344        T: StateMachineImpl;
345}
346
347/// Storage backend that can expose a pinned runtime reference.
348///
349/// This capability is separate from [`SRef`] and [`SMut`] because pinning is
350/// stronger than ordinary borrowing. A backend should implement this only when
351/// it can prove the runtime value will not be moved for the lifetime of the
352/// storage object. [`SPinBox`](crate::SPinBox) does; ordinary owned storage
353/// intentionally does not.
354///
355/// Use this bound for read-only methods that must call APIs taking
356/// `Pin<&Self>`:
357///
358/// ```ignore
359/// fn stable_address<S>(self: &State<S, Self, Ready>) -> usize
360/// where
361///     S: magicstatemachines::SPinRef,
362/// {
363///     magicstatemachines::pin_ref(self).stable_address()
364/// }
365/// ```
366pub trait SPinRef: SRef {
367    /// Borrows the runtime implementation as a pinned shared reference.
368    fn s_pin_ref<T, State>(inner: &Self::Inner<T, State>) -> Pin<&T>
369    where
370        T: StateMachineImpl;
371}
372
373/// Storage backend that can expose a pinned mutable runtime reference.
374///
375/// This is the capability required by pinned transition effects. It does not
376/// imply [`SMut`]: a backend may safely provide `Pin<&mut T>` for `!Unpin`
377/// values while still refusing to provide `&mut T`.
378pub trait SPinMut: SPinRef {
379    /// Mutably borrows the runtime implementation as a pinned reference.
380    fn s_pin_mut<T, State>(inner: &mut Self::Inner<T, State>) -> Pin<&mut T>
381    where
382        T: StateMachineImpl;
383}
384
385/// Storage backend whose state token can be consumed by value.
386///
387/// Use this when an API must move the backend representation itself rather
388/// than just read or mutate the runtime value. Most transition methods only
389/// need [`SMut`].
390pub trait SMove: StateStorage {}
391
392/// A state token parameterized by storage, runtime implementation, and state.
393///
394/// The type parameters carry the whole proof:
395///
396/// - `Storage` selects how the runtime value is held, for example
397///   [`SOwned`](crate::SOwned), [`StorageStateOwnedBox`], or a mutable guard
398///   from shared storage.
399/// - `T` is the runtime implementation type, such as `Connection`.
400/// - `S` is the current state marker, such as `Disconnected` or
401///   `impl InOnline`.
402///
403/// `State` is intentionally a deref-like wrapper with very few inherent
404/// methods. State-machine behavior should be implemented on `T` with
405/// arbitrary self types, not added as generic convenience methods on `State`.
406/// That keeps the transition capability private to the implementation module.
407///
408/// ```ignore
409/// impl Connection {
410///     fn connect<S>(self: State<S, Self, Disconnected>) -> State<S, Self, Connected>
411///     where
412///         S: SMut,
413///     {
414///         magicstatemachines::transition!(self)
415///     }
416///
417///     fn endpoint<S>(self: &State<S, Self, impl InOnline>) -> &str
418///     where
419///         S: SRef,
420///     {
421///         &self.endpoint
422///     }
423/// }
424/// ```
425pub struct State<Storage, T, S>
426where
427    T: StateMachineImpl,
428    Storage: StateStorage,
429{
430    pub(crate) inner: Storage::Inner<T, S>,
431    pub(crate) marker: StateMarker<Storage, T, S>,
432}
433
434/// A result whose success and error values are states of the same machine.
435///
436/// This is useful for fallible state-machine methods where both branches
437/// return ownership of the same runtime value in different states:
438///
439/// ```ignore
440/// fn authenticate_if<S>(
441///     self: State<S, Connection, Connected>,
442///     user: Option<String>,
443/// ) -> SResult<S, Connection, Authenticated, Connected>
444/// where
445///     S: SMut,
446/// {
447///     match user {
448///         Some(user) => Ok(magicstatemachines::transition!(self, user)),
449///         None => Err(self),
450///     }
451/// }
452/// ```
453#[allow(type_alias_bounds)]
454pub type SResult<Storage, T, OkState, ErrState>
455where
456    Storage: StateStorage,
457    T: StateMachineImpl,
458= Result<State<Storage, T, OkState>, State<Storage, T, ErrState>>;
459
460/// A callable transition for generic [`State`] storage.
461#[doc(hidden)]
462pub struct StateTransitionCall<Storage, T, From, To>
463where
464    T: StateMachineImpl,
465    Storage: StateStorage,
466{
467    state: State<Storage, T, From>,
468    #[cfg(feature = "tracing")]
469    callsite: &'static Location<'static>,
470    marker: TransitionMarker<Storage, T, From, To>,
471}
472
473/// A callable transition that first routes through implementation-owned effects.
474#[doc(hidden)]
475pub struct EffectTransitionCall<Storage, T, From, To, Effect>
476where
477    T: StateMachineImpl,
478    Storage: StateStorage,
479{
480    state: State<Storage, T, From>,
481    callsite: TransitionCallsite,
482    marker: PhantomData<fn() -> (To, Effect)>,
483}
484
485/// A callable transition that runs a pinned implementation-side effect first.
486#[doc(hidden)]
487pub struct PinnedEffectTransitionCall<Storage, T, From, To, Effect>
488where
489    T: StateMachineImpl,
490    Storage: StateStorage,
491{
492    state: State<Storage, T, From>,
493    callsite: TransitionCallsite,
494    marker: PhantomData<fn() -> (To, Effect)>,
495}
496
497/// A callable concrete transition selected by [`StateKind`].
498#[doc(hidden)]
499pub struct ConcreteProofTransitionCall<Storage, T, From, To>
500where
501    T: StateMachineImpl,
502    Storage: StateStorage,
503{
504    state: State<Storage, T, From>,
505    callsite: TransitionCallsite,
506    marker: PhantomData<fn() -> To>,
507}
508
509/// A callable transition selected by the receiver state's marker kind.
510#[doc(hidden)]
511pub struct KindProofTransitionCall<Storage, T, From, Marker, To, Kind>
512where
513    T: StateMachineImpl,
514    Storage: StateStorage,
515    From: crate::StateTrait,
516    Marker: crate::StateMarker,
517    To: crate::ConcreteStateTrait,
518    Kind: StateKind,
519{
520    state: State<Storage, T, From>,
521    callsite: TransitionCallsite,
522    marker: PhantomData<fn() -> (Marker, To, Kind)>,
523}
524
525/// A callable transition proven through a generated state union.
526#[doc(hidden)]
527pub struct StateUnionProofTransitionCall<Storage, T, From, Marker, To>
528where
529    T: StateMachineImpl,
530    Storage: StateStorage,
531    From: crate::StateTrait,
532    Marker: StateUnionDiscriminant,
533    To: crate::ConcreteStateTrait,
534{
535    state: State<Storage, T, From>,
536    callsite: TransitionCallsite,
537    marker: PhantomData<fn() -> (Marker, To)>,
538}
539
540/// A callable pinned transition proven through a generated state union.
541#[doc(hidden)]
542pub struct PinnedStateUnionProofTransitionCall<Storage, T, From, Marker, To>
543where
544    T: StateMachineImpl,
545    Storage: StateStorage,
546    From: crate::StateTrait,
547    Marker: StateUnionDiscriminant,
548    To: crate::ConcreteStateTrait,
549{
550    state: State<Storage, T, From>,
551    callsite: TransitionCallsite,
552    marker: PhantomData<fn() -> (Marker, To)>,
553}
554
555/// A callable discriminated-union transition that returns to the original storage after transition.
556#[doc(hidden)]
557pub struct DiscriminatedTransitionCall<Storage, T, Marker, To>
558where
559    T: StateMachineImpl,
560    Storage: StateStorage,
561    Marker: StateUnionDiscriminant,
562{
563    state: DiscriminatedState<Storage, T, Marker>,
564    callsite: TransitionCallsite,
565    marker: PhantomData<fn() -> To>,
566}
567
568/// A callable pinned discriminated-union transition.
569#[doc(hidden)]
570pub struct PinnedDiscriminatedTransitionCall<Storage, T, Marker, To>
571where
572    T: StateMachineImpl,
573    Storage: StateStorage,
574    Marker: StateUnionDiscriminant,
575{
576    state: DiscriminatedState<Storage, T, Marker>,
577    callsite: TransitionCallsite,
578    marker: PhantomData<fn() -> To>,
579}
580
581#[cfg(feature = "tracing")]
582#[doc(hidden)]
583pub type TransitionCallsite = &'static Location<'static>;
584
585#[cfg(not(feature = "tracing"))]
586#[doc(hidden)]
587pub type TransitionCallsite = ();
588
589#[doc(hidden)]
590#[track_caller]
591pub fn transition_callsite() -> TransitionCallsite {
592    #[cfg(feature = "tracing")]
593    {
594        Location::caller()
595    }
596    #[cfg(not(feature = "tracing"))]
597    {}
598}
599
600impl<Storage, T, From, To> StateTransitionCall<Storage, T, From, To>
601where
602    T: StateMachineImpl,
603    Storage: StateStorage,
604{
605    #[doc(hidden)]
606    pub fn call<Args>(self, args: Args) -> State<Storage, T, To>
607    where
608        T::Standin: Transition<From, To>,
609        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
610        From: crate::StateTrait,
611        To: crate::ConcreteStateTrait,
612    {
613        Storage::complete_transition(self.state, args, {
614            #[cfg(feature = "tracing")]
615            {
616                self.callsite
617            }
618            #[cfg(not(feature = "tracing"))]
619            {}
620        })
621    }
622}
623
624impl<Storage, T, From, To, Effect> EffectTransitionCall<Storage, T, From, To, Effect>
625where
626    T: StateMachineImpl,
627    Storage: StateStorage,
628{
629    pub fn call<Args>(mut self, args: Args) -> State<Storage, T, To>
630    where
631        Storage: SMut,
632        T::Standin: Transition<From, To>,
633        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
634        From: crate::StateTrait,
635        To: crate::ConcreteStateTrait,
636        Effect: TransitionEffect<T, From, To, Args>,
637    {
638        Effect::apply(Storage::s_mut(&mut self.state.inner), args);
639        Storage::complete_transition_after_effect(self.state, self.callsite)
640    }
641}
642
643impl<Storage, T, From, To, Effect> PinnedEffectTransitionCall<Storage, T, From, To, Effect>
644where
645    T: StateMachineImpl,
646    Storage: StateStorage,
647{
648    pub fn call<Args>(mut self, args: Args) -> State<Storage, T, To>
649    where
650        Storage: SPinMut,
651        T::Standin: Transition<From, To>,
652        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
653        From: crate::StateTrait,
654        To: crate::ConcreteStateTrait,
655        Effect: PinnedTransitionEffect<T, From, To, Args>,
656    {
657        Effect::apply(Storage::s_pin_mut(&mut self.state.inner), args);
658        Storage::complete_transition_after_effect(self.state, self.callsite)
659    }
660}
661
662impl<Storage, T, From, To> ConcreteProofTransitionCall<Storage, T, From, To>
663where
664    T: StateMachineImpl,
665    Storage: StateStorage,
666{
667    pub fn call<Args>(mut self, args: Args) -> State<Storage, T, To>
668    where
669        T: TransitionEffectSelector<From, To>,
670        Storage: SMut,
671        T::Standin: Transition<From, To>,
672        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
673        From: crate::StateTrait,
674        To: crate::ConcreteStateTrait,
675        <T as TransitionEffectSelector<From, To>>::Effect: TransitionEffect<T, From, To, Args>,
676    {
677        <T as TransitionEffectSelector<From, To>>::Effect::apply(
678            Storage::s_mut(&mut self.state.inner),
679            args,
680        );
681        Storage::complete_transition_after_effect(self.state, self.callsite)
682    }
683}
684
685impl<Storage, T, From, Marker, To>
686    KindProofTransitionCall<Storage, T, From, Marker, To, ConcreteStateKind>
687where
688    T: StateMachineImpl,
689    Storage: StateStorage,
690    From: crate::StateTrait,
691    To: crate::ConcreteStateTrait,
692    Marker: crate::StateMarker,
693{
694    pub fn call<Args>(mut self, args: Args) -> State<Storage, T, To>
695    where
696        T: TransitionEffectSelector<From, To>,
697        Storage: SMut,
698        T::Standin: Transition<From, To>,
699        <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
700        From: crate::ConcreteStateTrait,
701        To: crate::ConcreteStateTrait,
702        <T as TransitionEffectSelector<From, To>>::Effect: TransitionEffect<T, From, To, Args>,
703    {
704        <T as TransitionEffectSelector<From, To>>::Effect::apply(
705            Storage::s_mut(&mut self.state.inner),
706            args,
707        );
708        Storage::complete_transition_after_effect(self.state, self.callsite)
709    }
710}
711
712impl<Storage, T, From, Marker, To>
713    KindProofTransitionCall<Storage, T, From, Marker, To, UnionStateKind>
714where
715    T: StateMachineImpl,
716    Storage: StateStorage,
717    From: crate::StateTrait,
718    To: crate::ConcreteStateTrait,
719    Marker: StateUnionDiscriminant,
720{
721    pub fn call<Args>(self, args: Args) -> State<Storage, T, To>
722    where
723        Storage: SMut,
724        From: crate::StateTrait + crate::In<Marker>,
725        Marker: StateUnionDiscriminatedTransition<T, To, Args>,
726        To: crate::ConcreteStateTrait,
727    {
728        let state = <From as crate::In<Marker>>::into_discriminated(self.state);
729        Marker::transition(state, args, self.callsite)
730    }
731}
732
733impl<Storage, T, From, Marker, To> StateUnionProofTransitionCall<Storage, T, From, Marker, To>
734where
735    T: StateMachineImpl,
736    Storage: StateStorage,
737    From: crate::StateTrait,
738    To: crate::ConcreteStateTrait,
739    Marker: StateUnionDiscriminant,
740{
741    pub fn call<Args>(mut self, args: Args) -> State<Storage, T, To>
742    where
743        Storage: SMut,
744        From: StateUnionErased<Marker>,
745        Marker: StateUnionSharedTransitionEffect<T, To, Args>,
746        To: crate::ConcreteStateTrait,
747    {
748        Marker::apply(Storage::s_mut(&mut self.state.inner), args);
749        Storage::complete_transition_after_effect(self.state, self.callsite)
750    }
751}
752
753impl<Storage, T, From, Marker, To> PinnedStateUnionProofTransitionCall<Storage, T, From, Marker, To>
754where
755    T: StateMachineImpl,
756    Storage: StateStorage,
757    From: crate::StateTrait,
758    To: crate::ConcreteStateTrait,
759    Marker: StateUnionDiscriminant,
760{
761    pub fn call<Args>(mut self, args: Args) -> State<Storage, T, To>
762    where
763        Storage: SPinMut,
764        From: StateUnionErased<Marker>,
765        Marker: crate::StateUnionSharedPinnedTransitionEffect<T, To, Args>,
766        To: crate::ConcreteStateTrait,
767    {
768        Marker::apply_pinned(Storage::s_pin_mut(&mut self.state.inner), args);
769        Storage::complete_transition_after_effect(self.state, self.callsite)
770    }
771}
772
773impl<Storage, T, Marker, To> DiscriminatedTransitionCall<Storage, T, Marker, To>
774where
775    T: StateMachineImpl,
776    Storage: StateStorage,
777    Marker: StateUnionDiscriminant,
778{
779    pub fn call<Args>(self, args: Args) -> State<Storage, T, To>
780    where
781        Storage: SMut,
782        Marker: StateUnionDiscriminatedTransition<T, To, Args>,
783        To: crate::ConcreteStateTrait,
784    {
785        Marker::transition(self.state, args, self.callsite)
786    }
787}
788
789impl<Storage, T, Marker, To> PinnedDiscriminatedTransitionCall<Storage, T, Marker, To>
790where
791    T: StateMachineImpl,
792    Storage: StateStorage,
793    Marker: StateUnionDiscriminant,
794{
795    pub fn call<Args>(self, args: Args) -> State<Storage, T, To>
796    where
797        Storage: SPinMut,
798        Marker: crate::StateUnionDiscriminatedPinnedTransition<T, To, Args>,
799        To: crate::ConcreteStateTrait,
800    {
801        Marker::pinned_transition(self.state, args, self.callsite)
802    }
803}
804
805/// Creates a callable transition for generic state storage.
806#[must_use]
807#[track_caller]
808pub fn transition_state<Storage, T, S, Next>(
809    state: State<Storage, T, S>,
810    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
811) -> StateTransitionCall<Storage, T, S, Next>
812where
813    T: StateMachineImpl,
814    Storage: StateStorage,
815    T::Standin: Transition<S, Next>,
816    S: crate::StateTrait,
817    Next: crate::ConcreteStateTrait,
818{
819    StateTransitionCall {
820        state,
821        #[cfg(feature = "tracing")]
822        callsite: Location::caller(),
823        marker: PhantomData,
824    }
825}
826
827/// Creates a callable transition that runs implementation-side effects first.
828#[doc(hidden)]
829#[must_use]
830#[track_caller]
831pub fn transition_state_with_effect<Storage, T, S, Next, Effect>(
832    state: State<Storage, T, S>,
833    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
834) -> EffectTransitionCall<Storage, T, S, Next, Effect>
835where
836    T: StateMachineImpl,
837    Storage: StateStorage,
838    T::Standin: Transition<S, Next>,
839    S: crate::StateTrait,
840    Next: crate::ConcreteStateTrait,
841{
842    EffectTransitionCall {
843        state,
844        callsite: transition_callsite(),
845        marker: PhantomData,
846    }
847}
848
849/// Creates a callable transition that runs pinned implementation-side effects first.
850#[doc(hidden)]
851#[must_use]
852#[track_caller]
853pub fn transition_state_with_pinned_effect<Storage, T, S, Next, Effect>(
854    state: State<Storage, T, S>,
855    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
856) -> PinnedEffectTransitionCall<Storage, T, S, Next, Effect>
857where
858    T: StateMachineImpl,
859    Storage: StateStorage,
860    T::Standin: Transition<S, Next>,
861    S: crate::StateTrait,
862    Next: crate::ConcreteStateTrait,
863{
864    PinnedEffectTransitionCall {
865        state,
866        callsite: transition_callsite(),
867        marker: PhantomData,
868    }
869}
870
871/// Creates a callable pinned transition from a static union proof.
872#[doc(hidden)]
873#[must_use]
874#[track_caller]
875pub fn transition_state_with_static_union_pinned_proof<Storage, T, S, Marker, Next>(
876    state: State<Storage, T, S>,
877    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
878) -> PinnedStateUnionProofTransitionCall<Storage, T, S, Marker, Next>
879where
880    T: StateMachineImpl,
881    Storage: StateStorage,
882    S: crate::StateTrait + StateUnionErased<Marker>,
883    Marker: StateUnionDiscriminant + crate::StateUnionSharedPinnedEffect<T, Next>,
884    Next: crate::ConcreteStateTrait,
885{
886    PinnedStateUnionProofTransitionCall {
887        state,
888        callsite: transition_callsite(),
889        marker: PhantomData,
890    }
891}
892
893/// Creates a callable transition from a union-membership proof.
894#[doc(hidden)]
895#[must_use]
896#[track_caller]
897pub fn transition_state_with_union_proof<Storage, T, S, Marker, Next>(
898    proven: StateUnionProvenState<Storage, T, S, Marker, Next>,
899    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
900) -> StateUnionProofTransitionCall<Storage, T, S, Marker, Next>
901where
902    T: StateMachineImpl,
903    Storage: StateStorage,
904    S: StateUnionErased<Marker>,
905    Marker: StateUnionSharedEffect<T, Next>,
906    Next: crate::ConcreteStateTrait,
907{
908    StateUnionProofTransitionCall {
909        state: proven.state,
910        callsite: transition_callsite(),
911        marker: PhantomData,
912    }
913}
914
915/// Creates a callable transition from a concrete-state proof.
916#[doc(hidden)]
917#[must_use]
918#[track_caller]
919pub fn transition_state_with_concrete_proof<Storage, T, S, Marker, Next>(
920    proven: StateConcreteProvenState<Storage, T, S, Marker, Next>,
921    token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
922) -> EffectTransitionCall<Storage, T, S, Next, <T as TransitionEffectSelector<S, Next>>::Effect>
923where
924    T: StateMachineImpl + TransitionEffectSelector<S, Next>,
925    Storage: StateStorage,
926    T::Standin: Transition<S, Next>,
927    Marker: StateUnionDiscriminant,
928    S: crate::StateTrait,
929    Next: crate::ConcreteStateTrait,
930{
931    transition_state_with_effect(proven.state, token)
932}
933
934/// Creates a callable transition from an unresolved concrete-state proof.
935#[doc(hidden)]
936#[must_use]
937#[track_caller]
938pub fn transition_state_with_concrete_transition_proof<Storage, T, S, Marker, Next>(
939    proven: StateWithProof<Storage, T, S, StateConcreteTransitionProof<T, S, Marker, Next>>,
940    token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
941) -> EffectTransitionCall<Storage, T, S, Next, <T as TransitionEffectSelector<S, Next>>::Effect>
942where
943    T: StateMachineImpl + TransitionEffectSelector<S, Next>,
944    Storage: StateStorage,
945    T::Standin: Transition<S, Next>,
946    Marker: StateUnionDiscriminant,
947    S: crate::StateTrait,
948    Next: crate::ConcreteStateTrait,
949{
950    let StateWithProof {
951        state,
952        proof: _proof,
953    } = proven;
954    transition_state_with_effect(state, token)
955}
956
957/// Creates a callable transition from an unresolved union-membership proof.
958#[doc(hidden)]
959#[must_use]
960#[track_caller]
961pub fn transition_state_with_union_transition_proof<Storage, T, S, Marker, Next>(
962    proven: StateWithProof<Storage, T, S, StateUnionTransitionProof<T, S, Marker, Next>>,
963    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
964) -> StateUnionProofTransitionCall<Storage, T, S, Marker, Next>
965where
966    T: StateMachineImpl,
967    Storage: StateStorage,
968    S: StateUnionErased<Marker>,
969    Marker: StateUnionSharedEffect<T, Next>,
970    Next: crate::ConcreteStateTrait,
971{
972    let StateWithProof {
973        state,
974        proof: _proof,
975    } = proven;
976    StateUnionProofTransitionCall {
977        state,
978        callsite: transition_callsite(),
979        marker: PhantomData,
980    }
981}
982
983/// Creates a callable static union transition from a shared-body proof.
984#[doc(hidden)]
985#[must_use]
986#[track_caller]
987pub fn transition_state_with_static_union_proof<Storage, T, S, Marker, Next>(
988    state: State<Storage, T, S>,
989    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
990) -> StateUnionProofTransitionCall<Storage, T, S, Marker, Next>
991where
992    T: StateMachineImpl,
993    Storage: StateStorage,
994    S: crate::StateTrait + StateUnionErased<Marker> + crate::UnionTransitionProof<T, Marker, Next>,
995    Marker: StateUnionDiscriminant + StateUnionSharedEffect<T, Next>,
996    Next: crate::ConcreteStateTrait,
997{
998    StateUnionProofTransitionCall {
999        state,
1000        callsite: transition_callsite(),
1001        marker: PhantomData,
1002    }
1003}
1004
1005/// Creates a callable erased transition from a kind-selected proof.
1006#[doc(hidden)]
1007#[must_use]
1008#[track_caller]
1009pub fn transition_state_with_erased_transition_proof<Storage, T, S, Marker, Next, Proof>(
1010    proven: StateWithProof<Storage, T, S, Proof>,
1011    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
1012) -> StateUnionProofTransitionCall<Storage, T, S, Marker, Next>
1013where
1014    T: StateMachineImpl,
1015    Storage: StateStorage,
1016    S: crate::StateTrait,
1017    Marker: StateUnionDiscriminant,
1018    Next: crate::ConcreteStateTrait,
1019{
1020    let StateWithProof {
1021        state,
1022        proof: _proof,
1023    } = proven;
1024    StateUnionProofTransitionCall {
1025        state,
1026        callsite: transition_callsite(),
1027        marker: PhantomData,
1028    }
1029}
1030
1031/// Creates a concrete callable transition from a kind-selected proof.
1032#[doc(hidden)]
1033#[must_use]
1034#[track_caller]
1035pub fn transition_state_with_concrete_kind_proof<Storage, T, S, Marker, Next, Kind>(
1036    proven: StateWithProof<
1037        Storage,
1038        T,
1039        S,
1040        crate::TransitionProof<Storage, T, S, Marker, Next, Kind>,
1041    >,
1042    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
1043) -> ConcreteProofTransitionCall<Storage, T, S, Next>
1044where
1045    T: StateMachineImpl,
1046    Storage: StateStorage,
1047    S: crate::StateTrait,
1048    Marker: crate::StateMarker,
1049    Next: crate::ConcreteStateTrait,
1050    Kind: StateKind,
1051{
1052    let StateWithProof {
1053        state,
1054        proof: _proof,
1055    } = proven;
1056    ConcreteProofTransitionCall {
1057        state,
1058        callsite: transition_callsite(),
1059        marker: PhantomData,
1060    }
1061}
1062
1063/// Creates a callable transition from a kind-selected proof.
1064#[doc(hidden)]
1065#[must_use]
1066#[track_caller]
1067pub fn transition_state_with_kind_proof<Storage, T, S, Marker, Next, Kind>(
1068    proven: StateWithProof<
1069        Storage,
1070        T,
1071        S,
1072        crate::TransitionProof<Storage, T, S, Marker, Next, Kind>,
1073    >,
1074    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
1075) -> KindProofTransitionCall<Storage, T, S, Marker, Next, Kind>
1076where
1077    T: StateMachineImpl,
1078    Storage: StateStorage,
1079    S: crate::StateTrait,
1080    Marker: crate::StateMarker,
1081    Next: crate::ConcreteStateTrait,
1082    Kind: StateKind,
1083{
1084    let StateWithProof {
1085        state,
1086        proof: _proof,
1087    } = proven;
1088    KindProofTransitionCall {
1089        state,
1090        callsite: transition_callsite(),
1091        marker: PhantomData,
1092    }
1093}
1094
1095#[doc(hidden)]
1096pub fn transition_concrete_after_effect<Storage, T, From, To, Args, Effect>(
1097    mut state: State<Storage, T, From>,
1098    args: Args,
1099    callsite: TransitionCallsite,
1100) -> State<Storage, T, To>
1101where
1102    T: StateMachineImpl,
1103    Storage: SMut,
1104    From: crate::StateTrait,
1105    To: crate::ConcreteStateTrait,
1106    Effect: TransitionEffect<T, From, To, Args>,
1107{
1108    Effect::apply(Storage::s_mut(&mut state.inner), args);
1109    Storage::complete_transition_after_effect(state, callsite)
1110}
1111
1112#[doc(hidden)]
1113pub fn transition_concrete_after_pinned_effect<Storage, T, From, To, Args, Effect>(
1114    mut state: State<Storage, T, From>,
1115    args: Args,
1116    callsite: TransitionCallsite,
1117) -> State<Storage, T, To>
1118where
1119    T: StateMachineImpl,
1120    Storage: SPinMut,
1121    From: crate::StateTrait,
1122    To: crate::ConcreteStateTrait,
1123    Effect: PinnedTransitionEffect<T, From, To, Args>,
1124{
1125    Effect::apply(Storage::s_pin_mut(&mut state.inner), args);
1126    Storage::complete_transition_after_effect(state, callsite)
1127}
1128
1129/// Creates a callable discriminated-union transition that runs the exact concrete effect.
1130#[doc(hidden)]
1131#[must_use]
1132#[track_caller]
1133pub fn transition_discriminated_state<Storage, T, Marker, Next>(
1134    state: DiscriminatedState<Storage, T, Marker>,
1135    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
1136) -> DiscriminatedTransitionCall<Storage, T, Marker, Next>
1137where
1138    T: StateMachineImpl,
1139    Storage: StateStorage,
1140    Marker: StateUnionDiscriminant,
1141    Next: crate::StateTrait,
1142{
1143    DiscriminatedTransitionCall {
1144        state,
1145        callsite: transition_callsite(),
1146        marker: PhantomData,
1147    }
1148}
1149
1150/// Creates a callable pinned discriminated-union transition that runs the exact concrete effect.
1151#[doc(hidden)]
1152#[must_use]
1153#[track_caller]
1154pub fn transition_discriminated_state_pinned<Storage, T, Marker, Next>(
1155    state: DiscriminatedState<Storage, T, Marker>,
1156    _token: <Storage::Machine<T> as StateMachineImpl>::TransitionToken,
1157) -> PinnedDiscriminatedTransitionCall<Storage, T, Marker, Next>
1158where
1159    T: StateMachineImpl,
1160    Storage: StateStorage,
1161    Marker: StateUnionDiscriminant,
1162    Next: crate::StateTrait,
1163{
1164    PinnedDiscriminatedTransitionCall {
1165        state,
1166        callsite: transition_callsite(),
1167        marker: PhantomData,
1168    }
1169}
1170
1171/// Binds a generated union-transition proof selected by the target state.
1172#[doc(hidden)]
1173#[must_use]
1174pub fn proven_state<To, Storage, T, S>(
1175    state: State<Storage, T, S>,
1176) -> StateUnionProvenState<Storage, T, S, <To as StateUnionProofTarget<T, S>>::Marker, To>
1177where
1178    T: StateMachineImpl,
1179    Storage: StateStorage,
1180    S: StateUnionErased<<To as StateUnionProofTarget<T, S>>::Marker>,
1181    To: StateUnionProofTarget<T, S>,
1182{
1183    StateUnionProvenState {
1184        state,
1185        marker: PhantomData,
1186    }
1187}
1188
1189/// Binds a generated union-transition proof selected by a union marker.
1190#[doc(hidden)]
1191#[must_use]
1192pub fn proven_union_state<Marker, To, Storage, T, S>(
1193    state: State<Storage, T, S>,
1194) -> StateUnionProvenState<Storage, T, S, Marker, To>
1195where
1196    T: StateMachineImpl,
1197    Storage: StateStorage,
1198    S: StateUnionErased<Marker>,
1199    Marker: StateUnionSharedEffect<T, To>,
1200    To: crate::ConcreteStateTrait,
1201{
1202    StateUnionProvenState {
1203        state,
1204        marker: PhantomData,
1205    }
1206}
1207
1208/// Borrows a state's runtime value through its storage's pin guarantee.
1209///
1210/// This is a free function rather than an inherent `State` method so generic
1211/// state-machine APIs stay focused on receiver types and transitions. Use it
1212/// when a method accepts `&State<S, T, Current>` and needs to call an API on
1213/// `T` that requires `Pin<&T>`.
1214#[must_use]
1215pub fn pin_ref<Storage, T, S>(state: &State<Storage, T, S>) -> Pin<&T>
1216where
1217    T: StateMachineImpl,
1218    Storage: SPinRef,
1219{
1220    Storage::s_pin_ref(&state.inner)
1221}
1222
1223/// Mutably borrows a state's runtime value through its storage's pin guarantee.
1224///
1225/// Most pinned transitions should use `pinned transition` plus
1226/// [`transition!(pin state, ...)`](macro@crate::transition) instead of calling
1227/// this directly. It is provided for implementation methods that need to call
1228/// additional pinned APIs before deciding whether to transition.
1229pub fn pin_mut<Storage, T, S>(state: &mut State<Storage, T, S>) -> Pin<&mut T>
1230where
1231    T: StateMachineImpl,
1232    Storage: SPinMut,
1233{
1234    Storage::s_pin_mut(&mut state.inner)
1235}
1236
1237impl<Storage, T, S> State<Storage, T, S>
1238where
1239    T: StateMachineImpl,
1240    Storage: StateStorage,
1241{
1242    pub(crate) fn from_inner(inner: Storage::Inner<T, S>) -> Self {
1243        Self {
1244            inner,
1245            marker: PhantomData,
1246        }
1247    }
1248
1249    /// Binds a generated union-transition proof to this state.
1250    #[doc(hidden)]
1251    #[must_use]
1252    pub fn with<Marker, To, Kind>(
1253        self,
1254        proof: crate::TransitionProof<Storage, T, S, Marker, To, Kind>,
1255    ) -> StateWithProof<Storage, T, S, crate::TransitionProof<Storage, T, S, Marker, To, Kind>>
1256    where
1257        S: crate::StateTrait,
1258        Marker: crate::StateMarker,
1259        To: crate::ConcreteStateTrait,
1260        Kind: crate::StateKind,
1261    {
1262        StateWithProof { state: self, proof }
1263    }
1264}
1265
1266impl<T, S> State<StorageStateOwned, T, S>
1267where
1268    T: StateMachineImpl,
1269{
1270    /// Wraps an implementation in an initial directly owned state.
1271    ///
1272    /// This is the normal entry point for a state machine. It only compiles
1273    /// when the definition crate declared `S` as an initial state for
1274    /// `T::Standin`.
1275    ///
1276    /// ```ignore
1277    /// use magicstatemachines::{SOwned, State};
1278    /// use test_def::states::Disconnected;
1279    ///
1280    /// let disconnected: State<SOwned, Connection, Disconnected> =
1281    ///     State::new(Connection::new("localhost:8080"));
1282    /// ```
1283    ///
1284    /// To move the state into another owned container later, create that
1285    /// container from the returned state token instead of constructing raw
1286    /// `T` again.
1287    #[must_use]
1288    pub fn new(value: T) -> Self
1289    where
1290        T::Standin: Initial<S>,
1291    {
1292        State {
1293            inner: <StorageStateOwned as StateStorageNew>::new(value),
1294            marker: PhantomData,
1295        }
1296    }
1297}
1298
1299impl<T, S> State<StorageStateOwnedBox, T, S>
1300where
1301    T: StateMachineImpl,
1302{
1303    /// Moves a directly owned state into `Box` storage without changing its state.
1304    ///
1305    /// This mirrors `Box::new`, but it takes `State<SOwned, T, S>` instead of
1306    /// raw `T` so the current state is preserved:
1307    ///
1308    /// ```ignore
1309    /// let owned: State<SOwned, Connection, Connected> = connection.connect();
1310    /// let boxed: SBox<Connection, Connected> = SBox::new(owned);
1311    /// ```
1312    #[must_use]
1313    pub fn new(state: State<StorageStateOwned, T, S>) -> Self {
1314        State {
1315            inner: crate::StateOwned {
1316                value: Box::new(state.inner.value),
1317                state: PhantomData,
1318                #[cfg(feature = "tracing")]
1319                trace: state.inner.trace,
1320            },
1321            marker: PhantomData,
1322        }
1323    }
1324
1325    /// Moves this boxed state back into direct owned storage.
1326    ///
1327    /// This consumes the box and returns `State<SOwned, T, S>`. The state
1328    /// marker is unchanged, so methods available before boxing remain
1329    /// available after unboxing.
1330    ///
1331    /// ```ignore
1332    /// let boxed: SBox<Connection, Connected> = SBox::new(owned);
1333    /// let owned_again: State<SOwned, Connection, Connected> = SBox::unbox(boxed);
1334    /// ```
1335    #[must_use]
1336    pub fn unbox(state: Self) -> State<StorageStateOwned, T, S> {
1337        State {
1338            inner: crate::StateOwned {
1339                value: *state.inner.value,
1340                state: PhantomData,
1341                #[cfg(feature = "tracing")]
1342                trace: state.inner.trace,
1343            },
1344            marker: PhantomData,
1345        }
1346    }
1347}
1348
1349impl<T, S> State<StorageStateOwnedPinBox, T, S>
1350where
1351    T: StateMachineImpl,
1352{
1353    /// Pins an already boxed state in place without changing its state.
1354    ///
1355    /// Pinning must happen to the boxed allocation. For that reason this
1356    /// constructor consumes [`SBox`] rather than `SOwned`:
1357    ///
1358    /// ```ignore
1359    /// let boxed: SBox<Connection, Connected> = SBox::new(owned);
1360    /// let pinned: SPinBox<Connection, Connected> = SPinBox::new(boxed);
1361    /// ```
1362    #[must_use]
1363    pub fn new(state: State<StorageStateOwnedBox, T, S>) -> Self {
1364        State {
1365            inner: crate::StateOwned {
1366                value: Box::into_pin(state.inner.value),
1367                state: PhantomData,
1368                #[cfg(feature = "tracing")]
1369                trace: state.inner.trace,
1370            },
1371            marker: PhantomData,
1372        }
1373    }
1374
1375    /// Converts pinned box storage back to box storage when the runtime is `Unpin`.
1376    ///
1377    /// This is only available for `T: Unpin`; otherwise the pinning guarantee
1378    /// must be preserved.
1379    ///
1380    /// ```compile_fail
1381    /// use core::marker::PhantomPinned;
1382    /// use magicstatemachines::{
1383    ///     Initial, SBox, SOwned, SPinBox, State, StateMachineImpl, States,
1384    /// };
1385    ///
1386    /// struct Machine;
1387    /// struct Runtime {
1388    ///     _pin: PhantomPinned,
1389    /// }
1390    /// struct Token;
1391    ///
1392    /// States! {
1393    ///     Ready;
1394    /// }
1395    ///
1396    /// impl Initial<Ready> for Machine {}
1397    ///
1398    /// impl StateMachineImpl for Runtime {
1399    ///     type Standin = Machine;
1400    ///     type Impl = Self;
1401    ///     type TransitionToken = Token;
1402    /// }
1403    ///
1404    /// let ready = State::<SOwned, _, Ready>::new(Runtime {
1405    ///     _pin: PhantomPinned,
1406    /// });
1407    /// let pinned: SPinBox<Runtime, Ready> = SPinBox::new(SBox::new(ready));
1408    ///
1409    /// // `Runtime` is `!Unpin`, so the pinned allocation cannot be turned
1410    /// // back into an ordinary box.
1411    /// let _boxed = SPinBox::into_boxed(pinned);
1412    /// ```
1413    #[must_use]
1414    pub fn into_boxed(state: Self) -> State<StorageStateOwnedBox, T, S>
1415    where
1416        T: Unpin,
1417    {
1418        State {
1419            inner: crate::StateOwned {
1420                value: Pin::into_inner(state.inner.value),
1421                state: PhantomData,
1422                #[cfg(feature = "tracing")]
1423                trace: state.inner.trace,
1424            },
1425            marker: PhantomData,
1426        }
1427    }
1428}
1429
1430#[cfg(feature = "unique-rc-arc")]
1431impl<T, S> State<StorageStateOwnedUniqueRc, T, S>
1432where
1433    T: StateMachineImpl,
1434{
1435    /// Moves a directly owned state into `UniqueRc` storage without changing its state.
1436    ///
1437    /// This API is available only with the `unique-rc-arc` feature because
1438    /// `UniqueRc` itself is nightly-only.
1439    #[must_use]
1440    pub fn new(state: State<StorageStateOwned, T, S>) -> Self {
1441        State {
1442            inner: crate::StateOwned {
1443                value: UniqueRc::new(state.inner.value),
1444                state: PhantomData,
1445                #[cfg(feature = "tracing")]
1446                trace: state.inner.trace,
1447            },
1448            marker: PhantomData,
1449        }
1450    }
1451}
1452
1453#[cfg(feature = "unique-rc-arc")]
1454impl<T, S> State<StorageStateOwnedUniqueArc, T, S>
1455where
1456    T: StateMachineImpl,
1457{
1458    /// Moves a directly owned state into `UniqueArc` storage without changing its state.
1459    ///
1460    /// This API is available only with the `unique-rc-arc` feature because
1461    /// `UniqueArc` itself is nightly-only.
1462    #[must_use]
1463    pub fn new(state: State<StorageStateOwned, T, S>) -> Self {
1464        State {
1465            inner: crate::StateOwned {
1466                value: UniqueArc::new(state.inner.value),
1467                state: PhantomData,
1468                #[cfg(feature = "tracing")]
1469                trace: state.inner.trace,
1470            },
1471            marker: PhantomData,
1472        }
1473    }
1474}
1475
1476impl<Storage, T, S> Deref for State<Storage, T, S>
1477where
1478    T: StateMachineImpl,
1479    Storage: SRef,
1480{
1481    type Target = T;
1482
1483    fn deref(&self) -> &Self::Target {
1484        Storage::s_ref(&self.inner)
1485    }
1486}
1487
1488impl<Storage, T, S> DerefMut for State<Storage, T, S>
1489where
1490    T: StateMachineImpl,
1491    Storage: SMut,
1492{
1493    fn deref_mut(&mut self) -> &mut Self::Target {
1494        Storage::s_mut(&mut self.inner)
1495    }
1496}