Skip to main content

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}