#annotations #compile-time #parser #structure #macro-derive

annotation-rs-beta

编译时注解解析器,用于Rust

1 个不稳定版本

0.1.0-beta2021年1月6日

#9 in #annotation

MIT/Apache

24KB
422

annotation-rs

编译时注解解析器,用于Rust

特性

注解

annotation-rs提供了一个派生宏Annotation,可以通过结构体StructStructTupleStructNoFieldStruct来创建注解结构,均受支持。

use annotation_rs::Annotation;

#[derive(Annotation)]
struct NoField;

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

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

类型

  • 字符串:Rust中的String
  • 布尔值:Rust中的bool
  • 整数:Rust中的任何整数类型。
  • 浮点数:Rust中的任何浮点数类型。
  • 对象:其他注解结构。
  • 枚举:定义枚举,记得使用enum_value=true选项。
  • Vec:T的Vec(T不能是对象、Vec或HashMap)。
  • HashMap:通过String Skey映射的T的HashMap。如果你想使字段可选,请在字段类型上使用Option<T>
use annotation_rs::{AnnotationEnumValue, Annotation};

#[derive(Annotation)]
struct Bar;

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

#[derive(Annotation)]
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
    #[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
}

选项

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

枚举

使用派生AnnotationEnumValue在枚举上创建枚举值类型。

use annotation_rs::AnnotationEnumValue;

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

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

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

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

使用synquote解析注解

可以在parse_macro_input!中使用annotation_rs::AnnotationStructures<T>

let annotations = syn::parse_macro_inpit!(input as annotation_rs::AnnotationStructures<Foo>);

如果您想从syn::Meta解析注解,请使用annotation_rs::AnnotationStructure::from_meta()
具有值的注解结构可以自动转换为标记。但每个字段的可见性必须是公共的。

use proc_macro::TokenStream;

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

fn derive_fn(input: TokenStream) -> TokenStream {
    let annotations = syn::parse_macro_input!(input as annotation_rs::AnnotationStructures<Foo>);
    let attrs = annotations.attrs;

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

生成派生宏

如果您想使用内置读取器生成器,请启用annotation_reader特性。宏generate_reader用于生成派生宏。

use annotation_rs::generate_reader;

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

该宏将生成一个公共派生,它可以用来读取 结构体 ,枚举联合体 的注解,并通过生成 实现 块来记录元数据。

读取注解

在结构体上使用生成的 derive 宏,你可以使用宏 has_annotationget_annotation 来处理结构体的注解。这个功能需要 nightly rustc,因为需要 proc_macro_hygiene

#![feature(proc_macro_hygiene)]
use annotation_rs::{get_annotation, has_annotation};

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

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

依赖项

~2MB
~43K SLoC