17个版本

0.4.0-rc.1 2024年8月15日
0.3.10 2024年5月23日
0.3.8 2024年3月24日
0.3.4 2023年11月29日
0.1.0 2023年2月15日

#706过程宏

Download history 398/week @ 2024-04-24 277/week @ 2024-05-01 379/week @ 2024-05-08 837/week @ 2024-05-15 1440/week @ 2024-05-22 327/week @ 2024-05-29 340/week @ 2024-06-05 268/week @ 2024-06-12 147/week @ 2024-06-19 233/week @ 2024-06-26 314/week @ 2024-07-03 321/week @ 2024-07-10 361/week @ 2024-07-17 449/week @ 2024-07-24 301/week @ 2024-07-31 536/week @ 2024-08-07

1,676 每月下载量
5 个crate中使用(通过 crux_core

Apache-2.0

43KB
891

Crux Macros

此crate提供三个derive宏(EffectExportCapability),可用于与 crux_core 及相关(或自定义)功能一起使用。

1. Effect

可以使用 Effect derive宏来创建Shell在执行Core的副作用时使用的effect枚举。它还为Capabilities结构体推导出 WithContext

默认情况下,生成的枚举名称为 Effect,但可以覆盖(见下文)。该宏还需要知道您app结构的名称(默认为 App,但可以指定)。

它还需要知道您使用且其请求类型为非单元结构体的任何功能(实现了 Operation 特性)的操作类型。

根据惯例,该宏实际上应被称为 WithContext,但名称 Effect 可能更有效地描述生成的代码。

它作为derive宏实现,而不是attribute宏,因为它需要在结构体本身内的非宏属性中进行配置(这是不可能通过attribute宏实现的)。

示例用法

如果您想生成名为 Effect 的枚举,并且您的app结构名为 App,并且您使用的功能仅具有单元操作,则可以简单地使用该宏而无需额外配置

#[derive(Effect)]
pub struct Capabilities {
    pub render: Render<Event>,
}

如果您希望生成的Effect枚举有不同的名称,可以指定另一个名称

#[derive(Effect)]
#[effect(name = "MyEffect")]
pub struct Capabilities {
    pub render: Render<Event>,
}

如果你的应用结构体(实现了 App 特性)的名字不是 App,你可以指定它的名字

#[derive(Effect)]
pub struct Capabilities {
    pub render: Render<Event>,
}

要同时指定 appname,你可以使用属性两次,如下所示

#[derive(Effect)]
#[effect(name = "MyEffect")]
pub struct Capabilities {
    pub render: Render<Event>,
}

或者,更地道的方法是将它们合并为一个用法,如下所示

#[derive(Effect)]
#[effect(name = "MyEffect")]
pub struct Capabilities {
    pub render: Render<Event>,
}

完整的用法可能看起来像这样

#[derive(Effect)]
#[effect(name = "MyEffect")]
pub struct CatFactCapabilities {
    pub http: Http<MyEvent>,
    pub key_value: KeyValue<MyEvent>,
    pub platform: Platform<MyEvent>,
    pub render: Render<MyEvent>,
    pub time: Time<MyEvent>,
}

2. 导出

Export 派生宏会在你的 shared_types 库的外部类型生成期间,生成用于注册你能力类型的代码。

要使用它,在你的 shared 包中声明一个 typegen 功能,然后使用 Export 派生宏注释你的 Capabilities 结构体

#[cfg_attr(feature = "typegen", derive(crux_core::macros::Export))]
#[derive(Effect)]
pub struct Capabilities {
    pub render: Render<Event>,
    pub http: Http<MyEvent>,
    //...
}

然后,在 shared_types 包的 build.rs 文件中,当你注册你的 App 时,你能力使用的类型也会被注册

use crux_core::typegen::TypeGen;
use shared::{App, Event};
use std::path::PathBuf;

fn main() {
    println!("cargo:rerun-if-changed=../shared");

    let mut gen = TypeGen::new();

    gen.register_app::<App>().expect("register");

    let output_root = PathBuf::from("./generated");

    gen.swift("SharedTypes", output_root.join("swift"))
        .expect("swift type gen failed");

    gen.java("com.example.counter.shared_types", output_root.join("java"))
        .expect("java type gen failed");

    gen.typescript("shared_types", output_root.join("typescript"))
        .expect("typescript type gen failed");
}

3. 能力

Capability 派生宏可以用于在编写自己的能力时实现 Capability 特性。它生成的代码类似于以下内容

impl<Ev> crux_core::capability::Capability<Ev> for Render<Ev> {
    type Operation = RenderOperation;
    type MappedSelf<MappedEv> = Render<MappedEv>;
    fn map_event<F, NewEv>(&self, f: F) -> Self::MappedSelf<NewEv>
    where
        F: Fn(NewEv) -> Ev + Send + Sync + Copy + 'static,
        Ev: 'static,
        NewEv: 'static,
    {
        Render::new(self.context.map_event(f))
    }
}

这允许你从一个现有的能力中派生出一个能力的实例,并将其适配到不同的 Event 类型,这在从较小的 Crux 应用程序组合 Crux 应用程序时非常有用,可以自动将子事件包装在父事件中。

依赖项

~0.6–1.1MB
~24K SLoC