Rust宏编程库pallet-revive-proc-macro的使用:高效代码生成与过程宏扩展

Rust宏编程库pallet-revive-proc-macro的使用:高效代码生成与过程宏扩展

安装

在项目目录中运行以下Cargo命令:

cargo add pallet-revive-proc-macro

或者在你的Cargo.toml中添加以下行:

pallet-revive-proc-macro = "0.3.1"

示例代码

以下是一个使用pallet-revive-proc-macro的完整示例:

// 引入proc_macro库
use proc_macro::TokenStream;
use pallet_revive_proc_macro::revive;

// 定义一个简单的结构体
#[revive]
struct MyStruct {
    field1: u32,
    field2: String,
}

// 使用宏生成的代码
#[test]
fn test_revive_macro() {
    let my_struct = MyStruct {
        field1: 42,
        field2: "hello".to_string(),
    };
    
    // 宏会自动为结构体生成特定的方法
    let serialized = my_struct.serialize();
    let deserialized = MyStruct::deserialize(&serialized).unwrap();
    
    assert_eq!(my_struct.field1, deserialized.field1);
    assert_eq!(my_struct.field2, deserialized.field2);
}

// 宏也可以用于枚举
#[revive]
enum MyEnum {
    Variant1(u32),
    Variant2 { name: String, value: i64 },
}

// 使用宏生成的枚举方法
#[test]
fn test_enum_macro() {
    let variant1 = MyEnum::Variant1(123);
    let variant2 = MyEnum::Variant2 {
        name: "test".to_string(),
        value: -456,
    };
    
    assert_eq!(variant1.serialize().len(), 5);
    assert!(variant2.deserialize(&variant2.serialize()).is_ok());
}

完整示例demo

下面是一个更完整的示例,展示如何在Substrate pallet开发中使用这个宏:

// 引入必要的库
use proc_macro::TokenStream;
use pallet_revive_proc_macro::revive;
use frame_support::pallet_prelude::*;

// 定义一个复杂的结构体用于存储账户信息
#[revive]
#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)]
pub struct AccountData<Balance> {
    pub free: Balance,
    pub reserved: Balance,
    pub misc: MiscData,
}

// 嵌套的结构体也需要使用宏
#[revive]
#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)]
pub struct MiscData {
    pub is_active: bool,
    pub last_update: u64,
}

// 定义一个复杂枚举
#[revive]
#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo)]
pub enum AccountEvent<AccountId, Balance> {
    Created(AccountId),
    BalanceSet { who: AccountId, amount: Balance },
    Destroyed(AccountId),
}

// 测试用例
#[test]
fn test_complex_types() {
    // 测试结构体
    let account_data = AccountData {
        free: 100u32,
        reserved: 50u32,
        misc: MiscData {
            is_active: true,
            last_update: 123456789,
        },
    };
    
    let serialized = account_data.serialize();
    let deserialized = AccountData::deserialize(&serialized).unwrap();
    assert_eq!(account_data, deserialized);
    
    // 测试枚举
    let event = AccountEvent::BalanceSet {
        who: 1u64,
        amount: 200u32,
    };
    
    let event_serialized = event.serialize();
    let event_deserialized = AccountEvent::deserialize(&event_serialized).unwrap();
    assert_eq!(event, event_deserialized);
}

功能说明

pallet-revive-proc-macro库提供了以下主要功能:

  1. 自动为结构体和枚举生成序列化/反序列化方法
  2. 简化Substrate pallet开发中的常见模式
  3. 提供高效的类型转换和代码生成

许可证

Apache-2.0


1 回复

Rust宏编程库pallet-revive-proc-macro的使用:高效代码生成与过程宏扩展

完整示例demo

以下是结合了内容中所有示例功能的完整demo:

// 引入必要的库和宏
use pallet_revive_proc_macro::{Revive, revive};
use serde_json;

// 1. 基础派生宏使用示例
#[derive(Revive)]
struct User {
    id: u64,
    username: String,
    is_active: bool,
}

// 2. 自定义属性宏示例
#[revive(name = "UserUtils", version = 1)]
impl User {
    fn create_guest() -> Self {
        Self {
            id: 0,
            username: "guest".to_string(),
            is_active: true,
        }
    }
}

// 3. 代码生成示例 - 生成builder模式
#[derive(Revive)]
#[revive(generate_builder)]
struct Product {
    id: u32,
    name: String,
    price: f64,
    #[revive(default = "vec![]")]
    tags: Vec<String>,
}

// 4. 元编程扩展示例 - 自动实现Serialize
#[revive(extend = "serde::Serialize")]
#[derive(Revive)]
struct Order {
    order_id: String,
    items: Vec<Product>,
    total: f64,
}

// 5. 条件编译支持示例
#[derive(Revive)]
#[revive(feature = "debug", generate_debug)]
struct Config {
    #[revive(skip)]
    secret_key: String,
    api_url: String,
    timeout: u64,
}

// 6. 自定义扩展示例
use pallet_revive_proc_macro::ReviveExtension;
use syn;
use quote::quote;

struct TimestampExtension;

impl ReviveExtension for TimestampExtension {
    fn extend(&self, ast: &mut syn::DeriveInput) -> proc_macro2::TokenStream {
        let name = &ast.ident;
        quote! {
            impl #name {
                pub fn timestamp(&self) -> u64 {
                    std::time::SystemTime::now()
                        .duration_since(std::time::UNIX_EPOCH)
                        .unwrap()
                        .as_secs()
                }
            }
        }
    }
}

#[derive(Revive)]
#[revive(extension = "TimestampExtension")]
struct LogEntry {
    message: String,
    level: u8,
}

fn main() {
    // 使用生成的builder创建Product实例
    let product = Product::builder()
        .id(1)
        .name("Rust Programming Book".to_string())
        .price(39.99)
        .build();
    
    println!("Product: {:?}", product);

    // 使用自动实现的Serialize
    let order = Order {
        order_id: "ORD-123".to_string(),
        items: vec![product],
        total: 39.99,
    };
    
    let json = serde_json::to_string(&order).unwrap();
    println!("Order JSON: {}", json);

    // 使用自定义扩展生成的方法
    let log = LogEntry {
        message: "System started".to_string(),
        level: 1,
    };
    println!("Log created at: {}", log.timestamp());

    // 条件编译功能测试
    #[cfg(feature = "debug")]
    {
        let config = Config {
            secret_key: "abc123".to_string(),
            api_url: "https://api.example.com".to_string(),
            timeout: 30,
        };
        println!("Debug config: {:?}", config);
    }
}

Cargo.toml配置示例

[package]
name = "revive-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
pallet-revive-proc-macro = "0.1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
syn = { version = "2.0", features = ["full"] }
quote = "1.0"

# 如果要测试条件编译功能,可以取消下面的注释
# [features]
# debug = []

这个完整示例展示了pallet-revive-proc-macro库的主要功能:

  1. 基础派生宏
  2. 自定义属性宏
  3. 自动生成builder模式
  4. 元编程扩展自动实现trait
  5. 条件编译支持
  6. 自定义扩展功能

您可以根据实际需求选择使用其中的部分或全部功能。

回到顶部