1 个不稳定版本
0.1.0 | 2023年9月24日 |
---|
2207 在 算法
24KB
313 行
摘要
一个简单的库,允许创建 Moore 或 Mealy 状态机。它围绕 StateMachine<S,E>
类型设计,并允许使用自定义的转换函数。
要求
- 所有状态需要是相同的类型
S
- 所有事件(输入)需要是相同的类型
E
- 转换函数在
self
上执行(以访问内部状态或事件列表)并需要遵循原型
其中输入 E 是触发事件,返回值是新状态。fn(&mut StateMachine<S, E>, E) -> S;
- 输出生成留给用户,以允许实现尽可能通用。您可以打印或调用外部函数以生成所需的输出
实现 Moore 状态机
- 定义转换函数,计算下一个状态,并使用该状态生成任何输出
实现 Mealy 状态机
- 定义转换函数,计算下一个状态,并使用该状态以及输入事件 E 生成任何输出
异步状态机的基本示例
+------------+
Event: 1 | | +----+
| V | | Event: 1
+->[false] [true]<--+
| | ^ |
+---+ | | Event: 0
Event: 0 +------------+
use state_machine::state_machine::AsyncStateMachine;
async fn main() -> Result<()> {
let mut fsm = AsyncStateMachine::<bool, usize>::new(5);
fsm.add_states(&mut vec![true, false])
.await
.add_transition(true, 0, |_fsm, _event| false)
.await
.add_transition(true, 1, |_fsm, _event| true)
.await
.add_transition(false, 0, |_fsm, _event| false)
.await
.add_transition(false, 1, |_fsm, _event| true)
.await
.set_state(false)
.await;
fsm.start().await.unwrap();
println!("State Machine under test: {:?}", fsm);
fsm.push_event(0).await.unwrap();
assert_eq!(fsm.current_state().await, false);
fsm.push_event(1).await.unwrap();
assert_eq!(fsm.current_state().await, true);
fsm.push_event(1).await.unwrap();
assert_eq!(fsm.current_state().await, true);
fsm.push_event(0).await.unwrap();
assert_eq!(fsm.current_state().await, false);
fsm.push_event(0).await.unwrap();
assert_eq!(fsm.current_state().await, false);
}
状态机的基本示例(使用原始类型)
+---->[1]----+
Event: 1 | | Event: 2
| V
[3] [2]
^ |
| | Event: 3
+------------+
use state_machine::primitives::StateMachine;
// Define a transition function. It can as general as we want!
fn tf(_fsm: &mut StateMachine<i32, i32>, event: i32) -> i32 {
match event {
1 => 1,
2 => 2,
3 => 3,
_ => panic!(), // Invalid transition
}
}
let mut fsm = StateMachine::<i32, i32>::new();
fsm.add_states(&mut vec![1, 2, 3]);
// We can even use captures as transition functions!
fsm.add_transition(1, 2, |_fsm, _event| {
// We are in state 1! Go to state 2! Ignore Input!
2
});
// If you prefer you can chain configuration methods together
fsm.add_transition(2, 3, tf)
.add_transition(3, 1, tf)
.set_state(1);
println!("{:?}", fsm);
assert_eq!(&1, fsm.execute(1));
assert_eq!(&2, fsm.execute(2));
assert_eq!(&3, fsm.execute(3));
依赖关系
~1.2–2.6MB
~55K SLoC