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