3个不稳定版本
0.2.0 | 2023年4月13日 |
---|---|
0.1.1 | 2023年4月12日 |
0.1.0 | 2023年4月12日 |
在算法中排名第2373
9KB
90 行
有限状态机
使用宏在Rust中创建有限状态机。宏生成一个结构体、事件枚举和特质以及一个决策特质。决策特质用于决定转换到哪个状态。每个状态都有一个函数,当进入该状态时自动调用。自动添加无效状态和结束状态。您还需要为每个转换实现一个函数。宏自动生成您需要实现的所有内容的特质,以便在编译时检查其有效性。
用法
use finite_state_machine::state_machine;
// Debug is only needed if the verbose feature is enabled
#[derive(Debug, Default)]
struct Data {
...
}
state_machine!(
// The name of the state machine and the type of the data, you can also use livetimes here
CircuitBreaker(Data);
// the first state will automatically become the start state, no matter the name
Closed {
Ok => Closed, // on Ok event go to Closed state
AmperageTooHigh => Open // on AmperageTooHigh event go to open state
},
Open {
AttemptReset => HalfOpen,
Wait => Open
},
HalfOpen {
Success => Closed,
AmperageTooHigh => Open,
MaxAttemps => End
}
);
use circuit_breaker::*;
// now you need to implement the decider trait which emits events which decide which state to transition to
impl Deciders for CircuitBreaker {
fn closed(&self) -> circuit_breaker::ClosedEvents {
if self.data.current_amperage > self.data.max_amperage {
circuit_breaker::ClosedEvents::AmperageTooHigh
} else {
circuit_breaker::ClosedEvents::Ok
}
}
...
}
// now we need to implement the transition trait for each state
impl ClosedTransitions for CircuitBreaker {
fn amperage_too_high(&mut self) -> Result<(), &'static str> {
self.data.tripped_at = Some(SystemTime::now());
Ok(())
}
fn ok(&mut self) -> Result<(), &'static str> {
self.data.current_amperage += 1;
std::thread::sleep(Duration::from_millis(500));
Ok(())
}
fn illegal(&mut self) {}
}
有关更多详细信息,请查看示例文件夹。
工作原理
- 宏将创建一个模块,其名称为状态机的名称,并转换为蛇形大小写。在示例中:
CircuitBreaker
->circuit_breaker
。 - 宏将生成一个决策特质。这个特质为每个状态都有一个函数。您需要为您的结构体实现这个特质。在我们的例子中
impl Deciders for CircuitBreaker
。决策函数只接受一个不可变引用&self
,并必须返回一个枚举,其中包含每个转换的变体。这个枚举由宏生成。在我们的例子中circuit_breaker::ClosedEvents
等。还有一个Illegal
变体,用于遇到结构体的非法/不可能状态时。这将转换到Invalid
状态。在孤立的状态机中,这不应该发生。但是如果您在更大的系统中使用状态机,这可能会发生。 - 为每个您创建的状态,将生成一个
<StateName>Transitions
特性,您需要为您的结构体实现它。在我们的例子中impl ClosedTransitions for CircuitBreaker
。这些函数会得到对 self 的可变引用&mut self
并必须返回一个Result<(), &'static str>
。&'static str
用于返回错误信息。如果您返回Err
,状态机将过渡到自动添加的无效状态。当进入此状态时,机器停止并返回错误信息。
调试
您可以通过启用特性 verbose
来获取更多关于状态机的信息。这将打印当前状态、转换和当前数据。