atomr_core/fsm_macro.rs
1//! `fsm!` declarative macro — terse `FiniteStateMachine` impls.
2//!
3//! ```ignore
4//! use atomr_core::fsm;
5//!
6//! #[derive(Clone, Eq, PartialEq, Debug)]
7//! enum Light { Idle, Running }
8//! enum Cmd { Go, Stop }
9//!
10//! struct Traffic;
11//!
12//! fsm! {
13//! Traffic, state = Light, data = u32, msg = Cmd;
14//! initial state = Light::Idle, data = 0;
15//! (Light::Idle, Cmd::Go) => |s, d| (Light::Running, *d + 1, None);
16//! (Light::Running, Cmd::Stop) => |s, d| (Light::Idle, *d, None);
17//! }
18//! ```
19//!
20//! Each arm receives `(state: &State, data: &Data)` and returns
21//! `(next_state, next_data, Option<Duration>)`.
22
23#[macro_export]
24macro_rules! fsm {
25 (
26 $self_ty:ty,
27 state = $state:ty,
28 data = $data:ty,
29 msg = $msg:ty;
30 initial state = $init_state:expr, data = $init_data:expr;
31 $(
32 ($pat_state:pat, $pat_msg:pat) => |$s:ident, $d:ident| ($next:expr, $ndata:expr, $timeout:expr);
33 )+
34 ) => {
35 impl $crate::actor::FiniteStateMachine for $self_ty {
36 type State = $state;
37 type Data = $data;
38 type Msg = $msg;
39
40 fn initial_state(&self) -> Self::State { $init_state }
41 fn initial_data(&self) -> Self::Data { $init_data }
42
43 fn transition(
44 &mut self,
45 current: &Self::State,
46 data: &Self::Data,
47 msg: Self::Msg,
48 ) -> ::core::option::Option<$crate::actor::FsmTransition<Self::State, Self::Data>> {
49 match (current, msg) {
50 $(
51 ($pat_state, $pat_msg) => {
52 let $s = current;
53 let $d = data;
54 ::core::option::Option::Some($crate::actor::FsmTransition {
55 next: $next,
56 data: $ndata,
57 timeout: $timeout,
58 })
59 }
60 )+
61 _ => ::core::option::Option::None,
62 }
63 }
64 }
65 };
66}