#golem #wit #back-end #macro #data #file #cloud

golem-rust-macro

方便在Rust中编写Golem后端的Golem Rust工具库

7个版本 (1个稳定版)

新版本 1.0.0 2024年8月19日
0.4.0 2024年7月26日
0.3.0 2024年6月19日
0.2.2 2024年4月30日

过程宏 中排名 774

Download history • Rust 包仓库 294/week @ 2024-04-29 • Rust 包仓库 9/week @ 2024-05-20 • Rust 包仓库 4/week @ 2024-06-10 • Rust 包仓库 150/week @ 2024-06-17 • Rust 包仓库 3/week @ 2024-06-24 • Rust 包仓库 101/week @ 2024-07-22 • Rust 包仓库 20/week @ 2024-07-29 • Rust 包仓库

每月下载量 121
golem-rust 中使用

Apache-2.0

49KB
750

Golem Rust

该crate包含一些Rust宏,方便在Rust中编写Golem云后端

  1. 将wit-bindgen派生数据类型和自定义领域模型数据类型之间派生出 FromInto 类型类。
  2. 从Rust代码生成wit文件。

添加到您的项目

$ cargo add golem-rust

1. 在生成数据类型和自定义领域模型之间转换

当在Golem中使用WIT文件时,wit-bindgen库会根据wit文件生成数据类型。使用这些数据类型有一些缺点,因此用户通常会创建自己的数据类型。为了轻松地在生成和领域数据类型之间转换,程序员需要实现样板化的 From<>Into<> 类型类。

该项目包含宏,可以自动实现这些类型类。

结构体

假设我们有

    pub struct Person {
        pub name: String,
        pub age: i32,
    }

    pub struct WitPerson {
        pub name: String,
        pub age: i32,
    }

我们可以通过在Person上标注 #[derive(golem_rust::WIT_From_Into))] 来使用宏帮助实现 FromInto 类型类。

    #[derive(golem_rust::WIT_From_Into))]
    pub struct Person {
        pub name: String,
        pub age: i32,
    }

然后以下代码可以无问题编译

    let me = Person {
        name: "Jaro".to_owned(),
        age: 32,
    };

    let converted: WitPerson = me.into();

自定义数据类型名称

上述宏假定我们从 From<>Into<> 推导的数据类型称为 WitPerson。默认情况下,宏假定数据类型的名称是 Wit + 注解数据类型名称。如果名称不同,我们需要添加 #[wit_type_name(DerivedName)] 属性。

    #[derive(golem_rust::WIT_From_Into))]
    #[wit_type_name(DerivedName)]
    pub struct Person {
        pub name: String,
        pub age: i32,
    }

字段重命名

如果派生数据类型中的字段名称不同,我们可以使用字段属性 #[rename_field("")]

    #[derive(golem_rust::WIT_From_Into))]
    #[wit_type_name(WitPerson)]
    pub struct Person {

        #[rename_field("name2")]
        pub name: String,

        #[rename_field("age2")]
        pub age: i32,
    }

枚举

与结构体非常相似,假设我们有以下枚举数据类型

    #[derive(golem_rust::WIT_From_Into))]
    #[wit_type_name(SimilarColors)] 
    pub enum Colors {
        Red,
        White,

        #[rename_field("Yellow2")]
        Yellow,
    }

    pub enum SimilarColors {
        Red,
        White,
        Yellow2,
    }

然后非常简单,我们可以使用 .into() 并将其编译。

    let yellow = Colors::Yellow;

    let wit_collors: SimilarColors = yellow.into();

更多示例可以在 golem-rust-example/src/main.rs 中找到。

2. 从 Rust 模块生成 WIT 文件。

假设我们正在构建一个由 Golem Cloud 提供支持的拍卖应用。我们希望支持一些基本功能,例如

  • 初始化拍卖
  • 获取所有拍卖
  • 关闭拍卖
  • 创建一个竞标者
  • 出价。同时,我们还需要一些数据类型来描述拍卖、竞标者、结果等。

WIT 文件本身可能看起来像这样

package auction:app

interface api {

    record bidder-id {
        bidder-id: string,
    }

    record auction-id {
        auction-id: string,
    }

    record auction {
        auction-id: auction-id, 
		name: string, 
		description: string, 
		starting-price: float32, 
		deadline: deadline,
    }

    variant bid-result {
        failure(string), 
 		success
    }

    type deadline = u64
                

    initialize: func(auction: auction)
                    

    bid: func(bidder-id: bidder-id, price: float32) -> bid-result
                    

    close-auction: func() -> option<bidder-id>
                    

    create-bidder: func(name: string, address: string) -> bidder-id
                    

    create-auction: func(name: string, description: string, starting-price: float32, deadline: u64) -> auction-id
                    

    get-auctions: func() -> list<auction>
                    
}

world golem-service {
    export api
}

在编写此文件时可能会出现许多错误,特别是如果您不熟悉 WIT。但大多数情况下,它只是一个可以避免的样板。

只需使用 #[golem_rust::create_wit_file] 宏来注释您的内部模块。

#[golem_rust::create_wit_file]
mod auction_app {
    
    struct BidderId {
        bidder_id: String 
    }

    struct AuctionId {
        auction_id: String
    }

    struct Auction {
        auction_id: AuctionId,
        name: String, 
        description: String,
        starting_price: f32,
        deadline: Deadline,
    }

    enum BidResult {
        Failure(String),
        Success 
    }

    type Deadline = u64;

    trait AuctionService {

        fn initialize(auction: Auction);

        fn bid(bidder_id: BidderId, price: f32) -> BidResult;

        fn close_auction() -> Option<BidderId>;

        fn create_bidder(name: String, address: String) -> BidderId;

        fn create_auction(name: String, description: String, starting_price: f32, deadline: u64) -> AuctionId;

        fn get_auctions() -> Vec<Auction>;
    }
}

这将生成位于项目根目录中的 generated.wit 文件。如果您想使生成的文件具有自定义名称,请将名称添加到属性中,例如 #[golem_rust::create_wit_file("auction_app_file.wit")]

WIT 文件生成细节

以下空的内模块

#[golem_rust::create_wit_file]
mod package_name {

}

转换为空的 WIT 文件,其包名来自模块名称

package package:name
    
interface api {

}

world golem-service {
    export api
}

因此接口名称始终为 api,它从 world geolem-service 导出

WIT 文件生成的其他规则

  • Rust struct 转换为 WIT record
  • Enum 根据枚举是否有关联数据转换为 variantenum
  • Option<>option<>
  • 数组以及 vec<>list<>
  • 类型别名 type Name = String 变为 type name = string
  • Box<> 被忽略,并处理内部类型。
  • 支持元组。
  • PascalCase 被替换为 kebab-case。
  • snake_case 被替换为 kebab-case。
  • 特质名称不重要。
  • 特质内的函数被翻译为 WIT 文件函数。
  • 它必须是内部模块,并且所有使用的类型都需要在模块内定义。
  • 如果模块中有多个特质,它们的内容将被连接成单个 wit 接口。

如何贡献

非常欢迎贡献。如果您发现了一个错误、不支持的使用案例,或者您认为错误消息不够好,请打开一个问题或提交一个 PR。这个库仍然处于早期开发阶段,尽管已经涵盖了某些用例,但反馈将有助于完善这个库。

golem-rust-examples

依赖于 golem-rust 的内部二进制项目。在这里您可以找到更多关于如何使用 golem-rust 的示例。

依赖项

~310–770KB
~18K SLoC