MST
星途 面试题库

面试题:Rust过程宏的高级应用

编写一个Rust过程宏,它可以对一个结构体的所有字段生成访问器(getter)和修改器(setter)方法。结构体的定义是动态的,并且可能包含不同的数据类型。请详细说明宏的实现步骤,并给出完整的代码。
43.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 实现步骤
    • 首先,需要解析输入的结构体定义,提取出结构体的名称和字段信息。
    • 然后,为每个字段生成对应的访问器(getter)和修改器(setter)方法。
    • 使用proc_macro crate 来创建过程宏。
  2. 完整代码
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(Accessor)]
pub fn accessor_derive(input: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    let struct_name = &ast.ident;
    let fields = match &ast.data {
        syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
        _ => panic!("Only structs are supported"),
    };

    let getters_and_setters = fields.iter().map(|field| {
        let field_name = &field.ident.expect("Field should have a name");
        let field_type = &field.ty;

        let getter_name = format!("get_{}", field_name);
        let setter_name = format!("set_{}", field_name);

        quote! {
            pub fn #getter_name(&self) -> &#field_type {
                &self.#field_name
            }

            pub fn #setter_name(&mut self, value: #field_type) {
                self.#field_name = value;
            }
        }
    });

    let expanded = quote! {
        impl #struct_name {
            #(#getters_and_setters)*
        }
    };

    expanded.into()
}

使用这个宏时,你可以这样定义结构体:

#[derive(Accessor)]
struct MyStruct {
    field1: i32,
    field2: String,
}

这样MyStruct就会自动拥有get_field1set_field1get_field2set_field2方法。