struct - rust -如何使用派生宏来解析结构的元信息?

标签 struct rust macros

我正在使用结构来构建数据库的架构,因此我需要结构的元信息。
假设我的架构结构定义如下:

#[derive(ParseStruct)]
pub struct User {

  #[field_attr( unique = true, default = "", index=["@hash", "@count"] )]
  pub name: String,

  #[field_attr( unique = true, default = "" )]
  pub username: String,

  pub description: Option<String>,
  pub age: u32
}
我想解析为以下结构:
pub struct Schema<T>{
  name: String,         // the struct name
  origin: T,            // the struct to be parse, like the User struct above.
  fields: Vec<Field>,   // the struct's fields
}

pub struct Field {
    field_name: String,
    field_type: String,
    field_attrs: FieldAttribute
}

pub struct FieldAttribute {
    unique: bool,
    default: String,
    index: Vec<String>   // Index of the database
}
我写了一个开始,但是我不知道如何继续写:
#[proc_macro_derive(ParseStruct)]
pub fn parse_struct_derive(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    let name = &ast.ident;
    
    let gen = quote! {
        impl #name {
            fn parsed_schema()-> Schema { 
               // return the parsed schema     
               //...           
            }
        }
    };
    gen.into()
}
预期结果:
use parse_struct::ParseStruct;

#[derive(ParseStruct)]
struct User{
    #[field_attr( unique = true, default = "", index=["@hash", "@count"] )]
    pub name: String
}

fn main() {
    let schema = User::parsed_schema();
    println!("{:#?}",schema);
}
我不知道如何实现它。
我只是最近才开始学习派生宏,还没有完全掌握它。很难在Internet上找到有用的有关衍生宏的教程。
请帮助我,谢谢。

最佳答案

使用proc_macro_derive(过程宏)
src/main.rs:

use print_struct_trait::PrintStruct;

#[derive(PrintStruct)]
struct Point {
    name: String,
    x: i32,
    y: i32,
}

fn main() {
    let point = Point {
        name: "origin".to_string(),
        x: 2,
        y: 3,
    };
    point.print();
}
输出:
key=name, value=origin, type=String
key=x, value=2, type=i32
key=y, value=3, type=i32
print_struct_derive/src/lib.rs:
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::spanned::Spanned;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(PrintStruct, attributes(serde))]
pub fn derive_signature(item: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(item as DeriveInput);
    let struct_name = &ast.ident;

    let fields = if let syn::Data::Struct(syn::DataStruct {
        fields: syn::Fields::Named(ref fields),
        ..
    }) = ast.data
    {
        fields
    } else {
        panic!("Only support Struct")
    };

    let mut keys = Vec::new();
    let mut idents = Vec::new();
    let mut types = Vec::new();

    for field in fields.named.iter() {
        let field_name: &syn::Ident = field.ident.as_ref().unwrap();
        let name: String = field_name.to_string();
        let literal_key_str = syn::LitStr::new(&name, field.span());
        let type_name = &field.ty;
        keys.push(quote! { #literal_key_str });
        idents.push(&field.ident);
        types.push(type_name.to_token_stream());
    }

    let expanded = quote! {
        impl PrintStruct for #struct_name {
            fn print(&self) {
                #(
                    println!(
                        "key={key}, value={value}, type={type_name}",
                        key = #keys,
                        value = self.#idents,
                        type_name = stringify!(#types)
                    );
                )*
            }
        }
    };
    expanded.into()
}
PrintStruct在github上的源代码
引用:
  • syn/examples/heapsize/
  • Procedural Macros in Rust (part 1) - YouTube
  • 关于struct - rust -如何使用派生宏来解析结构的元信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62837767/

    相关文章:

    c++ - 结构中的静态对象

    c - 尝试创建结构体数组时运行时检查失败 #2

    C++:在结构定义问题中指向结构的指针

    rust - 如何在源代码之外存储格式字符串模板?

    c - C语言中的LAMBDA语法

    scala - 检索将分配给 Scala 宏调用的值的名称

    c - 将 csv 文件读取到结构时出错

    rust - 我对泛型函数和枚举有问题

    c++ - 分配内存并调用 C++ 回调的 Rust 函数崩溃

    javascript - Sweet.js - 宏主体中的括号