1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::fmt::Debug;
#[macro_export]
macro_rules! next {
($state:ident) => {
(StateFn(stringify!($state), $state), Vec::new())
};
($state:ident, $output:expr) => {
(StateFn(stringify!($state), $state), $output)
};
}
#[macro_export]
macro_rules! state_fn {
($state:ident) => {
StateFn(stringify!($state), $state)
};
($m:ident::$state:ident) => {
StateFn(stringify!($state), $m::$state)
}
}
pub trait FsmTypes: Sized {
type Context: Send + Clone + Debug;
type Msg: Send + Clone + Debug;
type Output: Send + Clone + Debug;
}
pub struct StateFn<T: FsmTypes>(
pub &'static str,
pub fn(&mut T::Context, T::Msg) -> (StateFn<T>, Vec<T::Output>)
);
impl<T: FsmTypes> Clone for StateFn<T> {
fn clone(&self) -> StateFn<T> {
StateFn(self.0, self.1)
}
}
#[derive(Clone)]
pub struct Fsm<T: FsmTypes> {
pub state: StateFn<T>,
pub ctx: T::Context
}
impl<T: FsmTypes> Fsm<T> {
pub fn new(ctx: T::Context, state: StateFn<T>) -> Fsm<T> {
Fsm {
state: state,
ctx: ctx
}
}
pub fn get_state(&self) -> (&'static str, &T::Context) {
(self.state.0, &self.ctx)
}
pub fn send(&mut self, msg: T::Msg) -> Vec<T::Output> {
let StateFn(_name, f) = self.state;
let (new_state, output) = f(&mut self.ctx, msg);
self.state = new_state;
output
}
}