#enums #handler #state #bloc

enum_handler

用于为枚举变体生成处理器的宏

1个不稳定版本

0.1.0 2024年8月21日

#443Rust模式

Download history 102/week @ 2024-08-16

每月102次下载

MIT/Apache

45KB
1K SLoC

Rust枚举处理器派生宏

本项目提供了一种方便且高效的宏,用于处理Rust枚举。

#[derive(EnumHandler)]宏简化了匹配和处理不同枚举变体的过程,使得代码更简洁易读。

它生成了一个具有对枚举每个变体进行match语句的公共处理方法特征的特质,允许你轻松地单独处理每个案例。

// You declare the CounterEvent enum:

use enum_handler::EnumHandler;

#[derive(EnumHandler)]
pub enum CounterEvent {
    Increment,
    Decrement,
    Reset,
    Set(i32),
}

// and the enum_handler macro will generate the following code for you behind the scenes:

pub trait CounterEventHandler {
    fn on(&self, e: CounterEvent) -> () {
        match (e) {
            CounterEvent::Increment => self.on_increment(),
            CounterEvent::Decrement => self.on_decrement(),
            CounterEvent::Reset => self.on_reset(),
            CounterEvent::Set(arg) => self.on_set(arg),
        }
    }
    fn on_increment(&self) -> ();
    fn on_decrement(&self) -> ();
    fn on_reset(&self) -> ();
    fn on_set(&self, set: i32) -> ();
}

生成的代码可以高度自定义以满足你的特定需求。

例如,你可以指定

  • 生成的特质和方法名称
  • 异步或同步方法
  • 按值(默认,改变所有权)或按引用传递参数
  • 为方法生成默认实现
    • 指定返回值
  • 为每个方法指定公共返回类型
  • 指定生成的特质和方法的可见性
  • 将生成的代码输出到文件以进行调试
  • 模拟所有支持

项目结构

项目结构如下

描述
enum_handler 暴露#[enum_handler()]属性宏的库包。这是你将在项目中包含的包!
enum_handler_derive 实现#[derive(EnumHandler)]宏的过程宏包。
enum_handler_core 包含宏几乎所有逻辑的核心包。这个包在库和派生包之间共享。你可以在测试目录和enum_handler_core包中的tests.rs文件中看到示例。

配置

使用 #[enum_handler()] 属性宏,您可以通过指定以下选项来自定义生成的代码:

选项 类型 默认值 描述
trait_suffix String "Handler" 指定要附加到枚举名称上的生成特质的后缀。
trait_name String "" 如果指定,生成的特质将使用此名称而不是默认名称。
handler_name String on 指定通用处理方法的名称。这也会用作生成方法名称的前缀(分隔符为 _)。
return_type String () 指定每个方法的通用返回类型。
default_return_value String () 指定如果生成默认实现,每个方法的通用返回值。
is_async bool false 指定生成的函数应该是异步(true)还是同步(false)。
default_implementation bool true 指定是否应该为方法生成默认实现(true)或不是(false)。
visibility String "" 指定生成的特质的可见性和方法的可见性。如果没有指定,则使用枚举的可见性。
no_async_trait_macro bool false 指定是否使用 #[async_trait::async_trait] 宏(false)或不使用(true)。这仅当 is_asynctrue 时相关。必须将 async_trait 包包含在 [dependencies] 中。
mock_name String "" 如果指定,将使用此名称生成一个 mockall 特质。必须将 mockall 包包含在 [dev-dependencies] 中。
pass_args_by_ref bool false 指定是否应该通过引用(true)或通过值(false)传递参数。

示例

以下是一些使用 #[derive(EnumHandler)] 宏的示例:

异步方法

use enum_handler::EnumHandler;

#[derive(EnumHandler)]
#[enum_handler(is_async = true)]
pub enum CounterEvent {
    Increment,
    Decrement,
    Reset,
    Set(i32),
}

自定义特质名称

use enum_handler::EnumHandler;

#[derive(EnumHandler)]
#[enum_handler(trait_name = "CounterHandler")]

pub enum CounterEvent {
    Increment,
    Decrement,
    Reset,
    Set(i32),
}

自定义处理方法名称

use enum_handler::EnumHandler;

#[derive(EnumHandler)]
#[enum_handler(handler_name = "handle")]
pub enum CounterEvent {
    Increment,
    Decrement,
    Reset,
    Set(i32),
}

自定义返回类型

use enum_handler::EnumHandler;

#[derive(EnumHandler)]
#[enum_handler(return_type = "i32")]
pub enum CounterEvent {
    Increment,
    Decrement,
    Reset,
    Set(i32),
}

Mockall 支持

use enum_handler::EnumHandler;

#[derive(EnumHandler)]
#[enum_handler(mock_name = "MockCounterHandler")]
pub enum CounterEvent {
    Increment,
    Decrement,
    Reset,
    Set(i32),
}

将生成的代码写入文件

您可以将环境变量 ENUM_HANDLER_DEBUG 设置为将生成的代码写入文件。

ENUM_HANDLER_DEBUG=/tmp/enum_handler.rs cargo build
  • 如果文件大于 128kB,它将被截断。
  • 这仅适用于调试目的,不应在生产代码中使用。

如果您想使用 rustfmt 格式化生成的代码,可以将环境变量 ENUM_HANDLER_DEBUG_FORMAT 设置为 1

ENUM_HANDLER_DEBUG=/tmp/enum_handler.rs ENUM_HANDLER_DEBUG_FORMAT=1 cargo build
  • 如果可用,文件将使用 rustfmt 进行格式化。

您还可以使用 cargo-expand 来查看生成的代码

cargo install cargo-expand
cargo expand --help

已知问题

  • 此包正在积极开发中,未来可能会有破坏性更改。
  • 在未来的版本中,将对 #[async_trait::async_trait] 宏的使用进行改进。
  • 在未来的版本中,rustfmt 格式化将可定制。
  • 在未来的版本中,元组变体参数的名称将被更改。
  • 当前支持的最小Rust版本(MSRV)设置为1.80.1。这将在未来的版本中进行审查。

贡献

欢迎贡献!如果您有任何想法、建议或错误报告,请在 GitHub 仓库 上创建一个问题或提交一个拉取请求。

许可证

根据您的选择,许可方式为以下之一:

贡献

除非您明确表示,否则根据 Apache-2.0 许可证定义的,您有意提交以包含在工作中的任何贡献,都将按上述方式双许可,而不附加任何额外条款或条件。

依赖项

~0.7–1.1MB
~26K SLoC