Rust代码生成插件库rusteron-code-gen的使用,高效自动化生成Rust代码和宏扩展

rusteron-code-gen

rusteron-code-gen 是 Rusteron 项目内部使用的代码生成工具。它从 Aeron 的 C API 自动生成 Rust 绑定,减少手动工作并确保 rusteron-* 系列 crate 之间一致的包装接口。

用途

Aeron 的 C API 遵循可预测的结构模式。该工具解析这些 C 头文件并使用模板生成围绕原始 FFI 层的 Rust 包装器。它主要用于生成:

  • rusteron-client
  • rusteron-archive
  • rusteron-media-driver

通过自动化这一步骤,我们在跟踪 Aeron 上游变化时降低了维护成本并提高了可靠性。

注意: 该 crate 不适用于 Rusteron 项目之外的独立使用。

特性

  • 自动化代码生成 - 将 Aeron C 头文件转换为 Rust 安全 API
  • 基于模式的模板 - 利用 Aeron 的一致结构来最小化样板代码
  • 集成友好 - 输出直接用于 Rusteron 栈的生产模块中

使用方法

该 crate 通过内部工具(例如 just 脚本或 CI 管道)使用,不打算作为依赖项添加到消费者项目中。

安全性考虑

生成的代码在必要时包含 unsafe 块以与 Aeron 的低级构造接口。虽然大部分生成是自动化的,但偶尔可能需要手动审查和修补以确保正确性,特别是在 Aeron 引入 API 更改时。

完整示例代码

// 示例代码展示了如何使用 rusteron-code-gen 生成 Rust 绑定

// 假设我们有一个 Aeron 的 C 头文件 "aeron.h"
// 首先需要解析 C 头文件
use rusteron_code_gen::parser::parse_c_header;

let header_content = std::fs::read_to_string("aeron.h")?;
let parsed = parse_c_header(&header_content)?;

// 然后使用模板生成 Rust 代码
use rusteron_code_gen::generator::generate_rust_bindings;

let rust_code = generate_rust_bindings(&parsed, "aeron")?;

// 生成的代码可能包含类似这样的结构
#[repr(C)]
pub struct aeron_header_t {
    pub frame_length: i32,
    pub version: i8,
    pub flags: u8,
    pub type_: i16,
    pub reserved: i32,
}

// 以及 FFI 函数
extern "C" {
    pub fn aeron_init() -> i32;
    pub fn aeron_shutdown() -> i32;
}

// 生成的代码通常还包含安全的 Rust 包装器
pub struct AeronClient {
    // 内部 FFI 状态
}

impl AeronClient {
    pub fn new() -> Result<Self, AeronError> {
        unsafe {
            let result = aeron_init();
            if result != 0 {
                Err(AeronError::from_code(result))
            } else {
                Ok(Self { /*...*/ })
            }
        }
    }
}

impl Drop for AeronClient {
    fn drop(&mut self) {
        unsafe {
            aeron_shutdown();
        }
    }
}

请注意,实际使用中 rusteron-code-gen 通常作为构建过程的一部分运行,而不是直接包含在应用程序代码中。

完整示例 demo

// 示例展示了一个完整的构建脚本示例,用于生成 Aeron 客户端绑定

// build.rs
use std::path::PathBuf;
use std::process::Command;

fn main() {
    // 1. 定义 Aeron C 头文件路径
    let aeron_header = PathBuf::from("include/aeron.h");
    
    // 2. 调用 rusteron-code-gen 生成绑定
    let output = Command::new("rusteron-code-gen")
        .arg("--input")
        .arg(aeron_header.to_str().unwrap())
        .arg("--output")
        .arg("src/bindings.rs")
        .arg("--module")
        .arg("aeron_client")
        .output()
        .expect("Failed to generate bindings");
    
    if !output.status.success() {
        panic!("Binding generation failed: {}", String::from_utf8_lossy(&output.stderr));
    }
    
    println!("cargo:rerun-if-changed=include/aeron.h");
}

// src/lib.rs
mod bindings;
pub use bindings::*;

// 生成的 src/bindings.rs 内容示例:
#[repr(C)]
pub struct aeron_context_t {
    pub is_direct: bool,
    pub use_conductor: bool,
    // 其他字段...
}

extern "C" {
    pub fn aeron_context_init(context: *mut aeron_context_t) -> i32;
    pub fn aeron_context_close(context: *mut aeron_context_t) -> i32;
}

// 安全包装器
pub struct AeronContext {
    inner: *mut aeron_context_t,
}

impl AeronContext {
    pub fn new() -> Result<Self, AeronError> {
        unsafe {
            let mut context = std::ptr::null_mut();
            let result = aeron_context_init(&mut context);
            if result != 0 {
                Err(AeronError::from_code(result))
            } else {
                Ok(Self { inner: context })
            }
        }
    }
}

impl Drop for AeronContext {
    fn drop(&mut self) {
        unsafe {
            aeron_context_close(self.inner);
        }
    }
}

1 回复

Rust代码生成插件库rusteron-code-gen使用指南

介绍

rusteron-code-gen 是一个强大的 Rust 代码生成工具库,旨在通过自动化代码生成来提高开发效率。它特别适合以下场景:

  • 减少重复性代码编写
  • 自动生成样板代码
  • 宏扩展和元编程
  • 根据数据结构自动生成相关实现

安装

在 Cargo.toml 中添加依赖:

[dependencies]
rusteron-code-gen = "0.4"

基本使用方法

1. 生成结构体实现

use rusteron_code_gen::code_gen;

#[code_gen]
struct Person {
    name: String,  // 姓名
    age: u32,      // 年龄
    email: Option<String>,  // 可选邮箱
}

这将自动为 Person 结构体生成 new()gettersetter 方法。

2. 自定义生成规则

use rusteron_code_gen::code_gen;

#[code_gen(
    derive(Debug, Clone, PartialEq),  // 自动派生常用trait
    impl_display,  // 实现Display trait
    builder  // 生成builder模式
)]
struct Book {
    title: String,   // 书名
    author: String,  // 作者
    isbn: String,   // ISBN号
    price: f64,     // 价格
}

这会为 Book 结构体:

  • 自动派生 Debug, ClonePartialEq trait
  • 实现 Display trait
  • 生成 builder 模式实现

3. 宏扩展

use rusteron_code_gen::expand_macro;

#[expand_macro]
macro_rules! vec_str {
    ($($element:expr),*) => {
        vec![$($element.to_string()),*]  // 将元素转换为字符串并收集到vec中
    };
}

这将扩展宏定义并提供更好的编译时检查和错误信息。

高级功能

1. 生成枚举实现

use rusteron_code_gen::code_gen;

#[code_gen(
    derive(Debug, Clone),  // 自动派生
    impl_from,  // 生成From实现
    impl_display  // 生成Display实现
)]
enum Status {
    Active,     // 活跃状态
    Inactive,   // 非活跃状态
    Suspended,  // 暂停状态
}

2. 生成 trait 实现

use rusteron_code_gen::code_gen;

trait Greet {
    fn greet(&self) -> String;  // 打招呼方法
}

#[code_gen(impl_trait = "Greet")]
struct User {
    name: String,  // 用户名
}

// 自动生成:
// impl Greet for User {
//     fn greet(&self) -> String {
//         format!("Hello, {}!", self.name)
//     }
// }

3. 自定义代码模板

use rusteron_code_gen::code_gen;

#[code_gen(
    template = r#"
        impl {{type_name}} {
            pub fn is_valid(&self) -> bool {
                !self.name.is_empty() && self.age > 0
            }
        }
    "#
)]
struct Member {
    name: String,  // 成员名
    age: u32,     // 年龄
}

配置选项

rusteron-code-gen 支持多种配置选项:

选项 描述 示例
derive 自动派生 trait derive(Debug, Clone)
impl_display 实现 Display trait impl_display
builder 生成 builder 模式 builder
impl_from 为枚举生成 From 实现 impl_from
template 自定义代码模板 template = "..."
impl_trait 为类型实现指定 trait impl_trait = "TraitName"

最佳实践

  1. 保持生成的代码简单:生成的代码应该易于理解和维护
  2. 文档注释:为生成的代码添加文档注释
  3. 测试生成代码:像手写代码一样测试生成的代码
  4. 版本控制:将生成的代码也纳入版本控制

示例项目结构

my_project/
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── models/
│   │   ├── mod.rs
│   │   ├── user.rs  # 使用rusteron-code-gen生成的代码
│   │   └── product.rs
│   └── macros/
│       └── custom.rs  # 使用宏扩展功能

完整示例demo

基本结构体生成示例

// main.rs
use rusteron_code_gen::code_gen;

#[code_gen]
pub struct Employee {
    id: u32,
    name: String,
    department: String,
    salary: f64,
}

fn main() {
    let emp = Employee::new(1, "Alice".to_string(), "Engineering".to_string(), 85000.0);
    println!("Employee: {} - {}", emp.get_id(), emp.get_name());
}

Builder模式生成示例

// models/product.rs
use rusteron_code_gen::code_gen;

#[code_gen(
    derive(Debug, Clone),
    builder,
    impl_display
)]
pub struct Product {
    id: u32,
    name: String,
    price: f64,
    in_stock: bool,
}

// 使用示例
fn create_product() {
    let product = Product::builder()
        .id(101)
        .name("Rust编程书".to_string())
        .price(59.99)
        .in_stock(true)
        .build();
    println!("{}", product);
}

枚举和trait实现示例

// models/status.rs
use rusteron_code_gen::code_gen;

#[code_gen(
    derive(Debug, Clone, PartialEq),
    impl_from,
    impl_display
)]
pub enum OrderStatus {
    Pending,
    Processing,
    Shipped,
    Delivered,
    Cancelled,
}

trait StatusCheck {
    fn is_completed(&self) -> bool;
}

#[code_gen(impl_trait = "StatusCheck")]
impl OrderStatus {
    // 自动生成:
    // impl StatusCheck for OrderStatus {
    //     fn is_completed(&self) -> bool {
    //         matches!(self, OrderStatus::Delivered | OrderStatus::Cancelled)
    //     }
    // }
}

宏扩展示例

// macros/custom.rs
use rusteron_code_gen::expand_macro;

#[expand_macro]
macro_rules! hash_map {
    ($($key:expr => $value:expr),*) => {
        {
            let mut map = std::collections::HashMap::new();
            $(map.insert($key, $value);)*
            map
        }
    };
}

// 使用示例
fn create_map() {
    let map = hash_map! {
        "name" => "Bob",
        "age" => "30",
        "city" => "Shanghai"
    };
    println!("{:?}", map);
}
回到顶部