如何在 Rust 中惯用地实现重要的类型状态模式?

问题描述 投票:0回答:1

我正在尝试构建一个简单 CPU 的 FSM,它由大约 40 个状态组成,带有循环,以及跨整个 CPU 状态的许多变量的许多条件。这个 FSM 的运行就像一个简单的图灵机;读取内存单元(想想 u16 的向量),计算一些结果,并将它们存储回内存中。

我的问题是:这是如何在 Rust 中惯用地实现的?

按照我的考虑,你会做这样的事情:

  1. 有一个代表各州的基本枚举。
  2. 每个状态都有另一个枚举来表示转换(但也许全部都在同一个枚举中?)。
  3. 不知何故,您必须访问 CPU 状态(所有不同寄存器的值等)才能知道如何发出下一个状态转换,但为了提高效率,您需要能够传递不同的子集CPU 状态的一部分,但不知何故仅在计算后改变代表 CPU 状态的单个副本。
  4. 您可能可以构建一个“状态差异”向量,当您达到某些状态时可以立即应用它,这也有利于实现简单的调试器。

我对 Rust 很陌生,所以对这些复杂的组合类型问题进行建模仍然不是很自然。

如果您想了解到目前为止的情况,我这里有一个存储库:https://github.com/ijustlovemath/lrc3

rust design-patterns
1个回答
0
投票

实现此目的的一种方法是创建一个

Cpu<State>
,然后为每个状态创建一个结构体来承载所有特定于状态的数据,并为每个状态编写一个
impl
以提供转换到下一个状态的方法。

struct Cpu<State> {
    data: Vec<u16>,
    state: State,
}


struct State1 {
    foo: String
}

struct State2 {
    bar: usize
}

impl Cpu<State1> {
    fn transition(self) -> Cpu<State2> {
        let Self { data, state: State1 { foo } }  = self;
        let bar = foo.len();
        Cpu { data, state: State2 { bar } }
    }
}

您基本上已经在类型系统中编码了枚举变体。状态之间的有效转换作为方法公开,无效的转换无法表示。

© www.soinside.com 2019 - 2024. All rights reserved.