#state-machine #finite-state-machine #state-transition #fsm #input #framework #dsl

no-std rust-fsm

为 Rust 构建有限状态机的框架和 DSL

8 个版本 (5 个重大更改)

0.7.0 2024 年 6 月 1 日
0.6.2 2024 年 5 月 11 日
0.6.1 2022 年 12 月 24 日
0.6.0 2021 年 8 月 24 日
0.2.0 2019 年 5 月 22 日

#145Rust 模式

Download history 2410/week @ 2024-05-02 2527/week @ 2024-05-09 4654/week @ 2024-05-16 6663/week @ 2024-05-23 5462/week @ 2024-05-30 3961/week @ 2024-06-06 3114/week @ 2024-06-13 3056/week @ 2024-06-20 3452/week @ 2024-06-27 3954/week @ 2024-07-04 3209/week @ 2024-07-11 2997/week @ 2024-07-18 2733/week @ 2024-07-25 2901/week @ 2024-08-01 2394/week @ 2024-08-08 2923/week @ 2024-08-15

每月 <11,385 次下载
3 包中使用 (2 个直接使用)

MIT 许可证

21KB
79

为 Rust 构建有限状态机的框架和 DSL

Documentation Latest Version

《rust-fsm》包提供了一种简单通用的框架,用于在 Rust 中以最小的努力构建状态机。

此包的核心是 StateMachineImpl 特性。此特性允许开发者提供严格的状态机定义,例如指定其

  • 输入字母表 - 状态机作为输入接受的一组实体,并根据它们执行状态转换。
  • 可能的状态 - 该机器可能处于的状态集合。
  • 输出字母表 - 状态机可能作为其工作结果输出的实体集合。
  • 转换函数 - 根据当前状态和提供的输入更改状态机的状态的函数。
  • 输出函数 - 根据当前状态和提供的输入从输出字母表中输出内容的函数。
  • 机器的初始状态。

请注意,在实现层面上,这种抽象允许构建任何类型的状态机

  • 通过仅提供输入字母表、一组状态和转换函数来构建经典状态机。
  • 通过提供上述所有实体来构建 Mealy 机器。
  • 通过提供一个不依赖于提供的输入的输出函数来构建 Moore 机器。

功能标志

默认

  • std - 实现需要 std 环境的功能。见下文。
  • dsl - 从 rust-fsm 中重新导出 rust-fsm-dsl。建议保留此功能以获得最佳开发体验。

非默认

  • diagram - 在文档字符串中生成Mermaid状态图。见下文。

no_std环境中的使用

此库有一个名为std的功能,默认启用。您可以将此库导入为rust-fsm = { version = "0.7", default-features = false, features = ["dsl"] },以便在no_std环境中使用。这仅影响错误类型(Error trait仅在std中可用)。

DSL实现的重导出受名为dsl的功能控制,该功能默认启用。

使用

最初,此库旨在构建一个易于使用的DSL,用于在其上定义状态机。使用DSL需要连接一个额外的crate rust-fsm-dsl(这是由于过程宏系统的限制)。

使用DSL定义状态机

DSL由state_machine宏进行解析。以下是一个小示例。

use rust_fsm::*;

state_machine! {
    #[derive(Debug)]
    #[repr(C)]
    /// A Circuit Breaker state machine.
    circuit_breaker(Closed)

    Closed(Unsuccessful) => Open [SetupTimer],
    Open(TimerTriggered) => HalfOpen,
    HalfOpen => {
        Successful => Closed,
        Unsuccessful => Open [SetupTimer]
    }
}

此代码示例

  • 定义了一个名为circuit_breaker的状态机;
  • 为它推导了Debug trait。您在这里使用的所有属性(如#[repr(C)])将应用于此宏生成的所有类型。如果您想将属性或文档字符串应用于此宏生成的mod,只需将其放在宏调用之前即可。
  • 将此状态机的初始状态设置为Closed
  • 定义状态转换。例如:在HalfOpen状态下收到Successful输入时,机器必须移动到Closed状态;
  • 定义输出。例如:在Closed状态下收到Unsuccessful时,机器必须输出SetupTimer

可以使用以下方式使用此状态机

// Initialize the state machine. The state is `Closed` now.
let mut machine = circuit_breaker::StateMachine::new();
// Consume the `Successful` input. No state transition is performed.
let _ = machine.consume(&circuit_breaker::Input::Successful);
// Consume the `Unsuccesful` input. The machine is moved to the `Open`
// state. The output is `SetupTimer`.
let output = machine.consume(&circuit_breaker::Input::Unsuccessful).unwrap();
// Check the output
if let Some(circuit_breaker::Output::SetupTimer) = output {
    // Set up the timer...
}
// Check the state
if let circuit_breaker::State::Open = machine.state() {
    // Do something...
}

以下实体被生成

  • 一个空的实现结构circuit_breaker::Impl,该结构实现了StateMachineImpl trait。
  • 枚举circuit_breaker::Statecircuit_breaker::Inputcircuit_breaker::Output,分别代表状态、输入字母表和输出字母表。
  • 类型别名circuit_breaker::StateMachine,它展开为StateMachine<circuit_breaker::Impl>

请注意,如果在规范中没有输出,输出字母表是一个空枚举。由于许多Rust属性的技術限制,无法将其应用于任何属性(例如 deriverepr)。

state_machine 宏内部,您必须定义至少一个状态转换。

可见性

您可以通过以下方式指定可见性:

use rust_fsm::*;

state_machine! {
    pub CircuitBreaker(Closed)

    Closed(Unsuccessful) => Open [SetupTimer],
    Open(TimerTriggered) => HalfOpen,
    HalfOpen => {
        Successful => Closed,
        Unsuccessful => Open [SetupTimer],
    }
}

默认可见性为私有。

自定义字母表类型

您可以为输入、输出或状态提供自己的类型。所有这些都是可选的:您可以使用其中之一或同时使用所有这些类型。当前的限制是您必须提供一个完全限定的类型路径。

use rust_fsm::*;

pub enum Input {
    Successful,
    Unsuccessful,
    TimerTriggered,
}

pub enum State {
    Closed,
    HalfOpen,
    Open,
}

pub enum Output {
    SetupTimer,
}

state_machine! {
    #[state_machine(input(crate::Input), state(crate::State), output(crate::Output))]
    circuit_breaker(Closed)

    Closed(Unsuccessful) => Open [SetupTimer],
    Open(TimerTriggered) => HalfOpen,
    HalfOpen => {
        Successful => Closed,
        Unsuccessful => Open [SetupTimer]
    }
}

图表

state_machine 宏可以使用图表来注释您的状态机。这由非默认的 diagram 功能控制。这些图表以 Mermaid 格式生成。此功能将Mermaid脚本包含在文档页面中。

要查看实际效果,请下载存储库并运行:

cargo doc -p doc-example --open

image

无DSL

state_machine 宏的功能有限(例如,状态无法携带任何附加数据),因此在某些复杂情况下,用户可能希望手动编写更复杂的状态机。

构建状态机所需的所有操作就是实现 StateMachineImpl 特性,并使用它与提供的包装器之一(目前只有 StateMachine)一起使用。

您可以在 项目存储库 中看到一个电路断路器状态机的示例。

依赖关系

~0–480KB
~11K SLoC