#枚举 #状态 # derive # proc-macro

statenum

一个启用状态模式逻辑中枚举的库

1 个稳定版本

1.0.0 2023年9月5日

2360Rust 模式

MIT 许可证

13KB
50

statenum

statenum,代表 "state-enum",是一个过程宏属性,为枚举的每个变体生成一个特性和一个结构体。

安装

将以下依赖项添加到您的 Cargo.toml 文件中

[dependencies]
statenum = "1.0"

用法

要使用 statenum,请将 #[statenum] 属性添加到您的枚举定义中。默认情况下,生成的特性将命名为 State。您可以通过将名称作为宏的参数提供来重写此名称。

use statenum::statenum;
#[statenum]
enum RocketStage {
    Grounded,
    Launched,
    // and so on...
}

#[statenum("PayloadState")]
enum PayloadStage {
    Vacant,
    Packed,
    // and so on...
}

可见性

这将生成一个名为 State 的特性和为枚举的每个变体生成的结构体。枚举的可见性会传递到 statenum 的实现中。如果枚举被标记为 pub,则生成的结构体变体和特性也将标记为 pub。但是,如果枚举不是公共的,则生成的组件也不会是公共的。

mod hidden {
    use statenum::statenum;
    
    #[statenum]
    enum RocketStage {
        Grounded,
        Launched,
    }

    pub struct Rocket<Stage: State = Grounded> {
        stage: Stage,
    }
}

// This would cause an error because the enum `RocketStage` is marked as private.
// let grounded: hidden::Rocket<hidden::Grounded>;

// The same applies to the trait.
// trait PayloadState: hidden::State {}

示例

通常,Rust 中的状态模式需要使用多个结构体定义。以下示例演示了实现状态模式的典型方法,并来自 Jon Gjengset 所著的《Rust for Rustaceans》一书。

use std::marker::PhantomData;

struct Grounded;
struct Launched;
// and so on...

pub struct Rocket<Stage = Grounded> {
    stage: PhantomData<Stage>,
}

impl<Stage> Rocket<Stage> {
    // ...
}

impl Rocket<Grounded> {
    pub fn launch(self) -> Rocket<Launched> {
        Rocket::<Launched> { stage: PhantomData::<Launched> }
    }
}

impl Rocket<Launched> {
    pub fn accelerate(&mut self) {
        // ...
    }

    pub fn decelerate(&mut self) {
        // ...
    }
}

如果不指定任何特性名称,使用宏将创建一个名为 State 的特性,如下所示(有意忽略 PhantomData 方面)

use statenum::statenum;

#[statenum]
enum RocketStage {
    Grounded,
    Launched,
    // and so on...
}

pub struct Rocket<Stage: State = Grounded> {
    stage: Stage,
}

impl<Stage: State> Rocket<Stage> {
    // ...
}

impl Rocket<Grounded> {
    pub fn launch(self) -> Rocket<Launched> {
        Rocket::<Launched> { stage: Launched }
    }
}

impl Rocket<Launched> {
    pub fn accelerate(&mut self) {
        // ...
    }

    pub fn decelerate(&mut self) {
        // ...
    }
}

否则,如果您希望将特性命名为除 State 之外的其他名称,可以通过指定名称来完成

use statenum::statenum;

#[statenum("RocketState")]
enum RocketStage {
    Grounded,
    Launched,
    // and so on...
}

pub struct Rocket<Stage: RocketState = Grounded> {
    stage: Stage,
}

impl<Stage: RocketState> Rocket<Stage> {
    // ...
}

impl Rocket<Grounded> {
    pub fn launch(self) -> Rocket<Launched> {
        Rocket::<Launched> { stage: Launched }
    }
}

impl Rocket<Launched> {
    pub fn accelerate(&mut self) {
        // ...
    }

    pub fn decelerate(&mut self) {
        // ...
    }
}

许可证

statenum 根据 MIT 许可证分发。

依赖项

~275–730KB
~17K SLoC