简体   繁体   English

由宏生成的 rust struct 字段

[英]rust struct fields generating by macro

I want to create a macro which on the received model generates structures with all its fields and implements trait Default, but faced such problem.我想创建一个宏,它在接收到的模型上生成具有所有字段的结构并实现 trait Default,但遇到了这样的问题。 My macro struct_field!我的宏 struct_field! is recognized as a field, not a macro inside the model!.被识别为一个字段,而不是模型内的宏!。 Мaybe someone knows how to solve this problem Мaybe有人知道如何解决这个问题

macro_rules! struct_field {
    ($fild_name:ident: string = $def_val:expr,) => {
        pub $fild_name: Arc<RwLock<String>>
    };
    
    ($fild_name:ident: string = $def_val:expr, $($fields:tt)+) => {
        pub $fild_name: Arc<RwLock<String>>
        struct_field!($($fields)+)
    };

    ($fild_name:ident: bool = $def_val:expr,) => {
        pub enable_kernel_settings: Arc<AtomicBool>,
    };

    ($fild_name:ident: bool = $def_val:expr, $($fields:tt)+) => {
        pub $fild_name: Arc<AtomicBool>,
        struct_field!($($fields)+)
    };
}

macro_rules! model {
    ($model:ident { $($inner_model:ident : $inner_model_name:ident { $($fields:tt)+ },)+ }) => {
        pub struct $model {$(
                $inner_model: $inner_model_name,
        )+}

        $(pub struct $inner_model_name {
            struct_field!($($fields)+) // <-- error
        })+
    };
}

error:错误:

error: expected `:`, found `!`
--> .../mod.rs:43:29
   |
43 |                   struct_field!($($fields)+)
   |                               ^ expected `:`
...
48 | / model! {
49 | |     MainStruct {
50 | |         inner_struct1: InnerStruct1 {
51 | |             feild1: bool = true,
...  |
58 | |     }
59 | | }
   | |_- in this macro invocation

example:例子:

model! {
    MainStruct {
        inner_struct1: InnerStruct1 {
            feild1: bool = true,
        },
        inner_struct2: InnerStruct2 {
            feild1: bool = false,
            feild2: bool = false,
            feild3: string = "ignore",
        },
    }
}

expected result:预期结果:

pub struct MainStruct {
    inner_struct1: InnerStruct1,
    inner_struct2: InnerStruct2,
}

pub struct InnerStruct1 {
    feild1: Arc<AtomicBool>,
}

pub struct InnerStruct2 {
    feild1: Arc<AtomicBool>,
    feild2: Arc<AtomicBool>,
    feild3: Arc<RwLock<String>>
}

you can test this with "cargo expand" and you should be enabled rust-nightly您可以使用“cargo expand”对此进行测试,并且应该启用 rust-nightly

Contrary to C-like macros, Rust macros can only operate on valid AST nodes, that is, they can only be passed something that can be tokenized and, if needed, parsed to some extent, and can only "return" a valid AST node.与类 C 的宏相反,Rust 宏只能在有效的 AST 节点上运行,也就是说,它们只能传递可以被标记化的东西,如果需要,可以在某种程度上进行解析,并且只能“返回”一个有效的 AST 节点. This, in particular, rules out the invocation of a macro that would be extended as a field definition, because something like a: bool is not a valid AST node.这尤其排除了调用将扩展为字段定义的宏,因为类似a: bool的东西不是有效的 AST 节点。

It is still possible to make a macro to do what you want to do, using function-style procedural macros , but it may become somehow more convoluted.仍然可以使用函数风格的过程宏来制作宏来做你想做的事情,但它可能会变得更加复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM