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