Skip to main content

magicstatemachines/
lib.rs

1#![cfg_attr(
2    all(feature = "decompose", feature = "nightly-random"),
3    feature(random)
4)]
5#![cfg_attr(feature = "unique-rc-arc", feature(unique_rc_arc))]
6#![feature(
7    arbitrary_self_types,
8    associated_type_defaults,
9    auto_traits,
10    negative_impls
11)]
12#![deny(unsafe_code)]
13#![warn(missing_docs)]
14
15//! Ergonomic typestate wrappers for compiler-enforced state machines.
16//!
17//! This crate requires nightly Rust for `arbitrary_self_types`.
18//!
19//! MagicStateMachines lets a state-machine contract live separately from the
20//! runtime type that implements it. A definition crate owns the stand-in type,
21//! state marker ZSTs, initial states, legal transitions, and state unions. An
22//! implementation crate connects a runtime type to that contract with
23//! [`StateMachineImpl!`](macro@crate::StateMachineImpl) and exposes ordinary
24//! inherent methods whose receiver type carries the current state.
25//!
26//! The core receiver type is [`State<Storage, T, S>`], where `T` is the runtime
27//! implementation, `S` is the current state marker, and `Storage` selects how
28//! the runtime value is held. Methods usually constrain storage by capability:
29//! [`SRef`] for read-only access, [`SMut`] for mutable transitions, [`SPinMut`]
30//! for pinned transitions, and [`SMove`] when storage must move by value. This
31//! allows the same state-machine methods to work for owned values, boxes,
32//! pinned boxes, shared guard views, and custom storage backends.
33//!
34//! In the default configuration this crate denies unsafe code. The `dynZST`
35//! feature uses the external `dynzst` crate for thin erased ZST state markers.
36//! Without tracing, directly owned state wrappers are layout-transparent over
37//! the runtime data, and concrete-state transitions are statically dispatched.
38//! When state crosses a boundary the compiler cannot prove, such as shared
39//! storage behind `Rc`, `Arc`, `RefCell`, `Mutex`, or `RwLock`, the committed
40//! erased state is checked at the boundary before returning a typed view.
41//!
42//! State unions support methods over a set of states. A union such as
43//! `Online` generates a sealed membership trait such as `InOnline`, a
44//! discriminated state representation, and an enum such as `OnlineEnum`.
45//! Static union transitions use [`transition!`](macro@crate::transition) with
46//! the `const` form when all members share the same transition body. Dynamic
47//! union transitions use the `dyn` form when the concrete member must be
48//! discriminated first.
49
50mod contract;
51#[cfg(feature = "decompose")]
52mod decomposed;
53mod kind;
54mod macros;
55mod policy;
56mod proof;
57mod shared;
58mod state;
59mod state_trait;
60#[cfg(feature = "tracing")]
61/// Transition tracing support.
62///
63/// This module is available with the `tracing` feature. It contains the
64/// [`TraceEntry`] type stored by state wrappers when tracing is enabled.
65pub mod tracing;
66mod union;
67mod util;
68
69pub use contract::{Initial, StateMachineImpl, Transition, TransitionSignature};
70#[cfg(feature = "decompose")]
71pub use decomposed::{DecomposedData, DecomposedState, RecomposeError};
72pub use kind::{
73    ConcreteStateKind, RuntimeStateMarker, StateKind, StateMarker, StateRuntimeMarkerFor,
74    UnionStateKind,
75};
76pub use policy::{StateClone, StateCopy};
77#[doc(hidden)]
78pub use proof::StateUnionTransitionProof;
79#[doc(hidden)]
80pub use proof::UnionTransitionProof;
81pub use proof::{
82    StateConcreteProvenState, StateConcreteTransitionProof, StateProofTransition,
83    StateTransitionProofBind, StateUnionProvenState, StateWithProof, TransitionProof,
84};
85pub use shared::{
86    MutexStorage, RefCellStorage, RwLockStorage, SArc, SArcMutex, SArcRwLock, SMutView, SMutex,
87    SRc, SRcRefCell, SRefCell, SRefView, SRwLock, SharedBorrowState, SharedState, SharedStateError,
88    SharedStorage, SharedValue, StateMut, StateMutTransitionCall, StateRef, StorageStateMut,
89    StorageStateRef, WeakSArc, WeakSArcMutex, WeakSArcRwLock, WeakSRc, WeakSRcRefCell,
90    WrongStateError, transition_mut,
91};
92pub use state::{
93    ConcreteProofTransitionCall, DiscriminatedTransitionCall, EffectTransitionCall, InferenceKind,
94    InnerInference, InnerStateInference, KindProofTransitionCall, OuterInference,
95    PinnedDiscriminatedTransitionCall, PinnedEffectTransitionCall,
96    PinnedStateUnionProofTransitionCall, PinnedTransitionEffect, PinnedTransitionEffectSelector,
97    SBox, SMove, SMut, SOwned, SPin, SPinBox, SPinMut, SPinRef, SRef, SResult, State,
98    StateInference, StateOwned, StateStorage, StateStorageNew, StateTransitionCall,
99    StateUnionProofTransitionCall, StorageStateOwned, StorageStateOwnedBox,
100    StorageStateOwnedPinBox, TransitionCall, TransitionCallsite, TransitionEffect,
101    TransitionEffectSelector, complete_transition_after_effect, pin_mut, pin_ref, proven_state,
102    proven_union_state, transition, transition_callsite, transition_concrete_after_effect,
103    transition_concrete_after_pinned_effect, transition_discriminated_state,
104    transition_discriminated_state_pinned, transition_state,
105    transition_state_with_concrete_kind_proof, transition_state_with_concrete_proof,
106    transition_state_with_concrete_transition_proof, transition_state_with_effect,
107    transition_state_with_erased_transition_proof, transition_state_with_kind_proof,
108    transition_state_with_pinned_effect, transition_state_with_static_union_pinned_proof,
109    transition_state_with_static_union_proof, transition_state_with_union_proof,
110    transition_state_with_union_transition_proof,
111};
112#[cfg(feature = "unique-rc-arc")]
113pub use state::{StorageStateOwnedUniqueArc, StorageStateOwnedUniqueRc};
114#[doc(hidden)]
115pub use state_trait::ConcreteStateTrait;
116pub use state_trait::StateTrait;
117#[doc(hidden)]
118pub use state_trait::{ErasedState, clone_erased as clone_erased_state};
119#[cfg(feature = "tracing")]
120pub use tracing::TraceEntry;
121#[doc(hidden)]
122pub use union::StateUnionConcreteState;
123#[doc(hidden)]
124pub use union::StateUnionDiscriminatedPinnedTransition;
125#[doc(hidden)]
126pub use union::StateUnionDiscriminatedTransition;
127#[doc(hidden)]
128pub use union::{
129    DiscriminatedInner, SDiscriminated, StateUnionErased, StateUnionMember,
130    StateUnionProofMembership, StateUnionProofTarget, StateUnionRuntime, StateUnionSharedEffect,
131    StateUnionSharedPinnedEffect, StateUnionSharedPinnedTransitionEffect,
132    StateUnionSharedTransitionEffect, StateUnionState, StateUnionTransition,
133    concretize_discriminated_state, discriminate_state, discriminated_state_marker,
134    erased_state_type_id, rediscriminate_union_state, state_union_marker, undiscriminate_state,
135};
136pub use union::{DiscriminatedState, In, StateUnionDiscriminant};
137pub use util::EnumExt;
138
139#[doc(hidden)]
140pub mod __private {
141    pub use paste::paste;
142}
143
144#[cfg(test)]
145mod tests;