1use std::fmt::Debug;
2
3pub trait Fsm: Debug {
4 type State: Debug;
6 type Event: Debug;
7
8 type Context: Send + Sync;
10 type Error: Send + Sync;
11}
12
13pub trait State<F>
14where
15 F: Fsm,
16{}
17
18pub trait Event<F>
19where
20 F: Fsm,
21{}
22
23pub trait Transition<F, E>
24where
25 F: Fsm,
26 E: Event<F>,
27 Self: State<F>,
28{
29 type Next: State<F>;
30
31 fn send(self, event: E, ctx: F::Context) -> Result<Self::Next, F::Error>;
32}
33
34#[derive(Debug)]
38pub enum Sent<F>
39where
40 F: Fsm,
41{
42 Valid(F::State),
46
47 Invalid(F::State, F::Event),
49}
50
51impl<F> Sent<F>
52where
53 F: Fsm,
54{
55 pub fn state(self) -> F::State {
57 match self {
58 Sent::Valid(state) => state,
59 Sent::Invalid(state, _) => state,
60 }
61 }
62
63 pub fn try_valid(self) -> Result<F::State, Invalid<F>> {
65 match self {
66 Sent::Valid(state) => Ok(state),
67 Sent::Invalid(state, event) => {
68 let err = Invalid { state, event };
69 Err(err)
70 },
71 }
72 }
73}
74
75#[derive(Debug, thiserror::Error)]
77#[error("invalid event for state: state = {state:?}, event = {event:?}")]
78pub struct Invalid<F: Fsm> {
79 pub state: F::State,
81
82 pub event: F::Event,
84}