Skip to main content

statum_core/
lib.rs

1//! Core traits and helper types shared by Statum crates.
2//!
3//! Most users reach these through the top-level `statum` crate. This crate
4//! holds the small runtime surface that macro-generated code targets:
5//!
6//! - state marker traits
7//! - transition capability traits
8//! - runtime error and result types
9//! - projection helpers for event-log style rebuilds
10
11pub mod projection;
12
13/// A generated state marker type.
14///
15/// Every `#[state]` variant produces one marker type that implements
16/// `StateMarker`. The associated `Data` type is `()` for unit states and the
17/// tuple payload type for data-bearing states.
18pub trait StateMarker {
19    /// The payload type stored in machines for this state.
20    type Data;
21}
22
23/// A generated state marker with no payload.
24///
25/// Implemented for unit state variants like `Draft` or `Published`.
26pub trait UnitState: StateMarker<Data = ()> {}
27
28/// A generated state marker that carries payload data.
29///
30/// Implemented for tuple variants like `InReview(Assignment)`.
31pub trait DataState: StateMarker {}
32
33/// A machine that can transition directly to `Next`.
34///
35/// This is the stable trait-level view of `self.transition()`.
36pub trait CanTransitionTo<Next> {
37    /// The transition result type.
38    type Output;
39
40    /// Perform the transition.
41    fn transition_to(self) -> Self::Output;
42}
43
44/// A machine that can transition using `Data`.
45///
46/// This is the stable trait-level view of `self.transition_with(data)`.
47pub trait CanTransitionWith<Data> {
48    /// The next state selected by this transition.
49    type NextState;
50    /// The transition result type.
51    type Output;
52
53    /// Perform the transition with payload data.
54    fn transition_with_data(self, data: Data) -> Self::Output;
55}
56
57/// A machine that can transition by mapping its current state data into `Next`.
58///
59/// This is the stable trait-level view of `self.transition_map(...)`.
60pub trait CanTransitionMap<Next: StateMarker> {
61    /// The payload type stored in the current state.
62    type CurrentData;
63    /// The transition result type.
64    type Output;
65
66    /// Perform the transition by consuming the current state data and producing the next payload.
67    fn transition_map<F>(self, f: F) -> Self::Output
68    where
69        F: FnOnce(Self::CurrentData) -> Next::Data;
70}
71
72/// Errors returned by Statum runtime helpers.
73#[derive(Debug)]
74pub enum Error {
75    /// Returned when a runtime check determines the current state is invalid.
76    InvalidState,
77}
78
79/// Convenience result alias used by Statum APIs.
80///
81/// # Example
82///
83/// ```
84/// fn ensure_ready(ready: bool) -> statum_core::Result<()> {
85///     if ready {
86///         Ok(())
87///     } else {
88///         Err(statum_core::Error::InvalidState)
89///     }
90/// }
91///
92/// assert!(ensure_ready(true).is_ok());
93/// assert!(ensure_ready(false).is_err());
94/// ```
95pub type Result<T> = core::result::Result<T, Error>;
96
97impl<T> From<Error> for core::result::Result<T, Error> {
98    fn from(val: Error) -> Self {
99        Err(val)
100    }
101}
102
103impl core::fmt::Display for Error {
104    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
105        write!(fmt, "{self:?}")
106    }
107}
108
109impl std::error::Error for Error {}