#proc-macro #struct-fields #struct #iterable #generic #reference #iterate

struct_iterable

提供一个用于使结构体可迭代的proc宏的Rust库

1个不稳定版本

0.1.1 2023年5月10日
0.1.0 2023年5月10日

#582Cargo插件

Download history 3215/week @ 2024-03-14 3415/week @ 2024-03-21 3505/week @ 2024-03-28 3474/week @ 2024-04-04 4550/week @ 2024-04-11 3838/week @ 2024-04-18 3796/week @ 2024-04-25 3205/week @ 2024-05-02 3435/week @ 2024-05-09 4541/week @ 2024-05-16 3355/week @ 2024-05-23 4751/week @ 2024-05-30 4200/week @ 2024-06-06 4151/week @ 2024-06-13 3602/week @ 2024-06-20 3153/week @ 2024-06-27

16,083 每月下载量
17 包中(直接使用4个)

MIT 许可证

11KB

结构体可迭代

Struct Iterable 是一个Rust库,它提供了一个proc宏,用于使结构体可迭代。这允许您以通用方式遍历结构体的字段,每次迭代返回一个包含字段名称作为静态字符串和字段值的 dyn Any 引用的元组。

使用方法

首先,将 Struct Iterable 添加到您的 Cargo.toml

[dependencies]
struct_iterable = "0.1.1"

接下来,在您的Rust文件顶部包含该库

use struct_iterable::Iterable;

最后,将 #[derive(Iterable)] 属性添加到您的结构体中

#[derive(Iterable)]
struct MyStruct {
    field1: u32,
    field2: String,
    // etc.
}

现在,您可以遍历结构体实例的字段

let my_instance = MyStruct {
    field1: 42,
    field2: "Hello, world!".to_string(),
};

for (field_name, field_value) in my_instance.iter() {
    println!("{}: {:?}", field_name, field_value);
}

限制

  • 仅支持具有命名字段的 结构体。
  • 仅支持结构体,不支持枚举或联合。

实现

以下是proc宏的实现

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
use iterable_structs::Iterable;

#[proc_macro_derive(Iterable)]
pub fn derive_iterable(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let struct_name = input.ident;
    let fields = match input.data {
        Data::Struct(data_struct) => match data_struct.fields {
            Fields::Named(fields_named) => fields_named.named,
            _ => panic!("Only structs with named fields are supported"),
        },
        _ => panic!("Only structs are supported"),
    };

    let fields_iter = fields.iter().map(|field| {
        let field_ident = &field.ident;
        let field_name = field_ident.as_ref().unwrap().to_string();
        quote! {
            (#field_name, &(self.#field_ident) as &dyn std::any::Any)
        }
    });

    let expanded = quote! {
        impl Iterable for #struct_name {
            fn iter<'a>(&'a self) -> std::vec::IntoIter<(&'static str, &'a dyn std::any::Any)> {
                vec![
                    #(#fields_iter),*
                ].into_iter()
            }
        }
    };

    TokenStream::from(expanded)
}

该宏接收一个结构体的TokenStream,并将其展开为该结构体的Iterable trait实现。此trait提供了一个返回字段名称和值元组迭代器的iter方法。

贡献和许可证

Struct Iterable 是一个开源项目,欢迎贡献。无论您是在修复错误、改进文档还是提出新功能,您的努力都将受到高度赞赏!

如果您有兴趣贡献,请随时提交一个pull request。对于重大更改,请首先打开一个问题来讨论您想更改的内容。

请注意,此项目以贡献者行为准则发布。参与此项目即表示您同意遵守其条款。

Struct Iterable 根据 MIT 许可证进行分发。因此,您可以根据许可证条款自由使用、修改、分发和以任何适当方式私下使用它。

依赖项

~0.5–1.1MB
~25K SLoC