1#![no_std]
2
3use core::fmt::Debug;
4
5#[cfg(feature = "inspect")]
6pub mod schema;
7
8#[cfg(feature = "inspect")]
9pub use schema::{EventSchema, Inspectable, MachineSchema, SuperstateSchema, TransitionSchema};
10
11pub trait MachineState: Copy + Eq + Debug + Send + Sync + 'static {}
13
14impl<T> MachineState for T where T: Copy + Eq + Debug + Send + Sync + 'static {}
15
16pub trait SubstateOf<Super> {}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct TransitionError<S>
36where
37 S: MachineState,
38{
39 pub from: S,
40 pub event: &'static str,
41 pub kind: TransitionErrorKind,
42}
43
44impl<S> TransitionError<S>
45where
46 S: MachineState,
47{
48 pub fn invalid_transition(from: S, event: &'static str) -> Self {
49 Self {
50 from,
51 event,
52 kind: TransitionErrorKind::InvalidTransition,
53 }
54 }
55
56 pub fn guard_failed(from: S, event: &'static str, guard: &'static str) -> Self {
57 Self {
58 from,
59 event,
60 kind: TransitionErrorKind::GuardFailed { guard },
61 }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
66pub enum TransitionErrorKind {
67 InvalidTransition,
68 GuardFailed { guard: &'static str },
69 ActionFailed { action: &'static str },
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct GuardError {
78 pub guard: &'static str,
79 pub event: &'static str,
80 pub kind: TransitionErrorKind,
81}
82
83impl GuardError {
84 pub const fn new(guard: &'static str, event: &'static str) -> Self {
85 Self {
86 guard,
87 event,
88 kind: TransitionErrorKind::GuardFailed { guard },
89 }
90 }
91
92 pub const fn with_kind(
93 guard: &'static str,
94 event: &'static str,
95 kind: TransitionErrorKind,
96 ) -> Self {
97 Self { guard, event, kind }
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
103pub struct CallbackError<E> {
104 pub action: &'static str,
105 pub event: &'static str,
106 pub source: E,
107}
108
109impl<E> CallbackError<E> {
110 pub fn new(action: &'static str, event: &'static str, source: E) -> Self {
111 Self {
112 action,
113 event,
114 source,
115 }
116 }
117}
118
119#[derive(Debug, Clone, PartialEq, Eq)]
121pub enum EventError<E> {
122 Guard(GuardError),
123 Callback(CallbackError<E>),
124}
125
126impl<E> EventError<E> {
127 pub const fn guard(err: GuardError) -> Self {
128 Self::Guard(err)
129 }
130
131 pub fn callback(action: &'static str, event: &'static str, source: E) -> Self {
132 Self::Callback(CallbackError::new(action, event, source))
133 }
134}
135
136#[doc(hidden)]
137pub trait FallibleCallbackReturn<E> {
138 fn into_result(self) -> Result<(), E>;
139}
140
141impl<E> FallibleCallbackReturn<E> for () {
142 fn into_result(self) -> Result<(), E> {
143 Ok(())
144 }
145}
146
147impl<E> FallibleCallbackReturn<E> for Result<(), E> {
148 fn into_result(self) -> Result<(), E> {
149 self
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq)]
158pub enum DynamicError<E = ()> {
159 InvalidTransition {
161 from: &'static str,
162 event: &'static str,
163 },
164 GuardFailed {
166 guard: &'static str,
167 event: &'static str,
168 },
169 ActionFailed {
171 action: &'static str,
172 event: &'static str,
173 },
174 CallbackFailed {
176 action: &'static str,
177 event: &'static str,
178 source: E,
179 },
180 WrongState {
182 expected: &'static str,
183 actual: &'static str,
184 operation: &'static str,
185 },
186}
187
188impl<E> DynamicError<E> {
189 pub fn invalid_transition(from: &'static str, event: &'static str) -> Self {
190 Self::InvalidTransition { from, event }
191 }
192
193 pub fn guard_failed(guard: &'static str, event: &'static str) -> Self {
194 Self::GuardFailed { guard, event }
195 }
196
197 pub fn action_failed(action: &'static str, event: &'static str) -> Self {
198 Self::ActionFailed { action, event }
199 }
200
201 pub fn callback_failed(action: &'static str, event: &'static str, source: E) -> Self {
202 Self::CallbackFailed {
203 action,
204 event,
205 source,
206 }
207 }
208
209 pub fn wrong_state(
210 expected: &'static str,
211 actual: &'static str,
212 operation: &'static str,
213 ) -> Self {
214 Self::WrongState {
215 expected,
216 actual,
217 operation,
218 }
219 }
220
221 pub fn from_guard_error(err: GuardError) -> Self {
223 match err.kind {
224 TransitionErrorKind::GuardFailed { guard } => Self::GuardFailed {
225 guard,
226 event: err.event,
227 },
228 TransitionErrorKind::ActionFailed { action } => Self::ActionFailed {
229 action,
230 event: err.event,
231 },
232 TransitionErrorKind::InvalidTransition => Self::InvalidTransition {
233 from: "",
234 event: err.event,
235 },
236 }
237 }
238
239 pub fn from_event_error(err: EventError<E>) -> Self {
240 match err {
241 EventError::Guard(err) => Self::from_guard_error(err),
242 EventError::Callback(err) => Self::callback_failed(err.action, err.event, err.source),
243 }
244 }
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq)]
248pub enum AroundStage {
249 Before,
250 AfterSuccess,
251}
252
253#[derive(Debug, Clone)]
254pub enum AroundOutcome<S>
255where
256 S: MachineState,
257{
258 Proceed,
259 Abort(TransitionError<S>),
260}