5个版本

0.1.8 2020年7月10日
0.1.7 2020年7月10日
0.1.5 2020年6月18日

#750过程宏

每月26次 下载

MIT/Apache

29KB
423 代码行

Yui

Yui是Rust的属性读取器。

特性

属性结构

Yui提供了一个 derive 宏 YuiAttribute,可以通过 struct(结构体)、StructStructTupleStructNoFieldStruct 创建属性结构,所有这些都被支持。

use yui::YuiAttribute;

#[derive(YuiAttribute)]
struct NoField;

#[derive(YuiAttribute)]
struct Tuple(i32, String);

#[derive(YuiAttribute)]
struct Struct {
    int: i32,
    float: f64,
    bool: bool,
}

类型

  • String:Rust中的 String
  • Bool:Rust中的 bool
  • Integer:Rust中的任何整数类型。
  • Float:Rust中的任何浮点类型。
  • Object:其他属性结构。
  • Enum:定义枚举,请记得使用 enum_value=true 选项。
  • Vec:T的Vec(T不能是Object、Vec或HashMap)。
  • HashMap:通过 String Skey 映射T的HashMap。如果你想要使一个字段可选,在字段类型上使用 Option<T>
use yui::{YuiEnumValue, YuiAttribute};

#[derive(YuiAttribute)]
struct Bar;

#[derive(YuiEnumValue)]
enum SomeEnum {
    A,
    B
}

#[derive(YuiAttribute)]
struct Foo {
    pub string: String,
    pub bool: bool,
    pub int: i32, // or other integer types like u32 ...
    pub float: f32, // or other float types like f64
    pub object: Bar, // any defined object
    #[attribute_field(enum_value=true)]
    pub enum_field: SomeEnum, // have to add enum_value option
    pub list: Vec<i32>, // nested type of vec can`t be Object, Vec or HashMap
    pub map: std::collections::HashMap<String, SomeEnum>,
    pub optional: Option<i32> // optional field
}

选项

  • alias
    生成的读取器将使用给定的名称解析字段,而不是Rust中字段的名称。
    #[derive(YuiAttribute)]
    struct Foo {
        #[attribute_field(alias = "i32")]
        pub int32: i32,
    }
    
  • default
    为此字段设置默认值。如果解析时不存在该值,则将默认值设置为字段,即使该字段是可选的。ObjectVecHashMap 字段不能有默认值。
    #[derive(YuiAttribute)]
    struct Foo {
        #[attribute_field(default = 1024)]
        pub int32: i32
    }
    
  • enum_value
    在Enum类型字段上使用 enum_value=true

Enum

使用 derive YuiEnumValue 在 Enum 上创建一个 Enum 值类型。

use yui::YuiEnumValue;

#[derive(YuiEnumValue)]
enum SomeEnum {
    A,
    B
}

然后,枚举可以作为一个字段类型使用。

  • variant_value 属性
    自定义与变体对应的字符串值(默认是Rust中变体名称的蛇形命名法)。
use yui::YuiEnumValue;

#[derive(YuiEnumValue)]
enum SomeEnum {
    #[variant_value("aaa")] // default is 'a'
    A,
    B
}

使用 synquote 解析属性

yui::AttributeStructs<T> 可用于 parse_macro_input!

let attributes = syn::parse_macro_inpit!(input as yui::AttributeStructs<Foo>);

如果您想从 syn::Meta 解析属性,请使用 yui::AttributeStruct::from_meta()
带有值的属性结构可以自动转换为令牌。但是每个字段的可见性必须是公共的。

use proc_macro::TokenStream;

#[derive(YuiAttribute)]
struct Foo {
    #[attribute_field(default = 1024)]
    pub int32: i32
}

fn derive_fn(input: TokenStream) -> TokenStream {
    let attributes = syn::parse_macro_input!(input as yui::AttributeStructs<Foo>);
    let attrs = attributes.attrs;

    TokenStream::from(quote::quote! {
        fn get_attrs() -> Vec<Foo> {
            vec![#(#attrs),*]
        }
    })
}

生成 derive 宏

如果您想使用内置的读取生成器,请启用 generate-reader 功能。宏 generate_reader 用于生成 derive 宏。

use yui::generate_reader;

generated_reader!(
    MyDerive,
    [StructAttribute1, StructAttribute2],
    [FieldAttribute1, FieldAttribute2]
);

该宏将生成一个公共的 derive,它可以用于读取 structenumunion 的属性,并通过生成 impl 块来记录元数据。

读取属性

在结构体上使用生成的 derive 宏,并可以使用宏 has_attributeget_attribute 处理结构体的属性。该功能需要 nightly rustc,因为需要 proc_macro_hygiene

#![feature(proc_macro_hygiene)]
use yui::{get_attribute, has_attribute};

#[derive(MyDerive)]
#[StructAttribute1("some parameters")]
struct Foo {
    #[FieldAttribute1("some parameters")]
    field: i32
}

fn some_fn() {
    assert!(has_attribute!(Foo, StructAttribute1));
    assert!(has_attribute!(Foo::field, FieldAttribute1));
    let struct_attr1: Option<StructAttribute1> = get_attribute!(Foo, StructAttribute1);
    let field_attr1: Option<StructAttribute1> = get_attribute!(Foo::field, StructAttribute1);
}

依赖项

~2MB
~43K SLoC