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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::fmt;
use reducer::Reducer;
use state::State;
use action::Action;
pub struct StateMachine<'a, T>
where
T: 'a + Copy + Clone,
{
reducers: Vec<Box<&'a Reducer<T>>>,
state: State<T>,
}
impl<'a, T> StateMachine<'a, T>
where
T: 'a + Copy + Clone,
{
pub fn new(initial_state: T) -> StateMachine<'a, T> {
StateMachine {
reducers: Vec::new(),
state: State::new(&initial_state),
}
}
pub fn push_reducer(&mut self, reducer: &'a Reducer<T>) -> &mut Self {
self.reducers.push(Box::new(reducer));
self
}
pub fn process(&self, a: &Action) -> &Self {
let mut new_state = self.state.get_state();
for reducer in &self.reducers {
new_state = reducer.process(new_state, a);
}
self.state.set_state(&new_state);
self
}
pub fn get_state(&self) -> T {
self.state.get_state()
}
}
impl<'a, T> fmt::Debug for StateMachine<'a, T>
where
T: 'a + Copy + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "StateMachine {{ reducers: {:?} }}", self.reducers.len())
}
}
impl<'a, T> fmt::Display for StateMachine<'a, T>
where
T: 'a + Copy + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "StateMachine")
}
}
#[cfg(test)]
mod tests {
use super::*;
use action::Action;
struct IncrementReducer {}
impl Reducer<u32> for IncrementReducer {
fn process(&self, state: u32, action: &Action) -> u32 {
match action.cat {
"increment" => state + 1,
_ => state,
}
}
}
#[test]
fn can_get_state() {
let sm = StateMachine::new(0);
assert_eq!(sm.get_state(), 0);
}
#[test]
fn reducer_works() {
let mut sm = StateMachine::new(0);
sm.push_reducer(&IncrementReducer {});
assert_eq!(sm.get_state(), 0);
sm.process(&Action::new("increment", &[]));
assert_eq!(sm.get_state(), 1);
}
}