#darling #proc-macro-attributes #macro-derive #macro-helpers #struct #field #traits-structs

darling_core

用于在实现自定义 derive 时将属性读取到结构体中的过程宏库辅助工具。在您的代码中使用 https://crates.io/crates/darling。

58 个版本

0.20.10 2024 年 7 月 9 日
0.20.8 2024 年 2 月 23 日
0.20.3 2023 年 7 月 12 日
0.14.4 2023 年 3 月 9 日
0.2.0 2017 年 6 月 19 日

#446过程宏

Download history 1392513/week @ 2024-05-04 1505125/week @ 2024-05-11 1523361/week @ 2024-05-18 1498423/week @ 2024-05-25 1659535/week @ 2024-06-01 1640010/week @ 2024-06-08 1613254/week @ 2024-06-15 1617421/week @ 2024-06-22 1466315/week @ 2024-06-29 1653954/week @ 2024-07-06 1636889/week @ 2024-07-13 1694302/week @ 2024-07-20 1672305/week @ 2024-07-27 1701554/week @ 2024-08-03 1736649/week @ 2024-08-10 1503746/week @ 2024-08-17

6,901,366 每月下载量
7,603 个 Crates 中使用 (4 直接使用)

MIT 许可证

305KB
7K SLoC

Darling

Build Status Latest Version Rustc Version 1.56+

darling 是一个用于过程宏作者的 crate,它允许将属性解析到结构体中。在内部和 API 方面都受到了 serde 的极大启发。

优势

  • 易于声明性解析宏输入 - 以最少的时间投入使您的过程宏高度可控。
  • 出色的验证和错误处理,无需额外工作。当您的过程宏用户犯错时,darling 确保他们在源代码的适当位置获得错误标记,并提供“你是指”的建议以纠正拼写错误的字段。

使用方法

darling 提供了一系列可以派生或手动实现的 trait。

  1. FromMeta 用于从属性中的元项中提取值。实现可能是许多库可重用的,类似于 FromStrserde::Deserialize。为原始类型、一些 std 类型和一些 syn 类型提供了 trait 实现。
  2. FromDeriveInput 由每个依赖于 darling 的过程宏 crate 实现。这是输入解析的根;它获取对目标类型的身份、泛型和可见性的访问,并可以指定应从输入 AST 解析或转发哪些属性名称。
  3. FromField 由每个依赖于 darling 的过程宏 crate 实现。实现此 trait 的结构体将获取对字段身份(如果存在)、类型和可见性的访问。
  4. FromVariant 由每个依赖 darling 的 proc-macro 包实现或派生。派生此特性的结构体将能够访问变体的身份和内容,这可以像任何其他 darling 输入一样进行转换。
  5. FromAttributes 是更具体的 FromDeriveInputFromFieldFromVariant 特性的低级版本。派生此特性的结构体会获得一个元项提取器和错误收集器,它可以处理任何语法元素,包括特性和函数。这对于非 derive proc-macro 很有用。

附加模块

  • darling::ast 提供了表示 AST 的泛型类型。
  • darling::usage 提供了确定类型参数和生命周期在结构体或枚举中使用的特性和函数。
  • darling::util 提供了具有特殊 FromMeta 实现的辅助类型,例如 PathList

示例

use darling::{FromDeriveInput, FromMeta};

#[derive(Default, FromMeta)]
#[darling(default)]
pub struct Lorem {
    #[darling(rename = "sit")]
    ipsum: bool,
    dolor: Option<String>,
}

#[derive(FromDeriveInput)]
#[darling(attributes(my_crate), forward_attrs(allow, doc, cfg))]
pub struct MyTraitOpts {
    ident: syn::Ident,
    attrs: Vec<syn::Attribute>,
    lorem: Lorem,
}

上面的代码然后将能够解析此输入

/// A doc comment which will be available in `MyTraitOpts::attrs`.
#[derive(MyTrait)]
#[my_crate(lorem(dolor = "Hello", sit))]
pub struct ConsumingType;

属性宏

支持非 derive 属性宏。要解析属性宏的参数,在参数接收器类型上派生 FromMeta,然后使用 darling::ast::NestedMeta::parse_meta_list 将参数 TokenStream 转换为 Vec<NestedMeta>,然后将它传递到你的参数接收器类型上的派生 from_list 方法。这将生成一个正常的 darling::Result<T>,它可以像解析 DeriveInput 的结果一样使用。

宏代码

use darling::{Error, FromMeta};
use darling::ast::NestedMeta;
use syn::ItemFn;
use proc_macro::TokenStream;

#[derive(Debug, FromMeta)]
struct MacroArgs {
    #[darling(default)]
    timeout_ms: Option<u16>,
    path: String,
}

#[proc_macro_attribute]
pub fn your_attr(args: TokenStream, input: TokenStream) -> TokenStream {
    let attr_args = match NestedMeta::parse_meta_list(args.into()) {
        Ok(v) => v,
        Err(e) => { return TokenStream::from(Error::from(e).write_errors()); }
    };
    let _input = syn::parse_macro_input!(input as ItemFn);

    let _args = match MacroArgs::from_list(&attr_args) {
        Ok(v) => v,
        Err(e) => { return TokenStream::from(e.write_errors()); }
    };

    // do things with `args`
    unimplemented!()
}

消费代码

use your_crate::your_attr;

#[your_attr(path = "hello", timeout_ms = 15)]
fn do_stuff() {
    println!("Hello");
}

特性

Darling 的特性旨在为实际项目提供良好的支持。

  • 默认值:支持结构和字段级别的默认值,使用与 serde 相同的路径语法。此外,Option<T>darling::util::Flag 字段是内在可选的;对于这些,你不需要声明 #[darling(default)]
  • 字段重命名:字段在使用和后端代码中可以有不同的名称。
  • 自动填充字段:派生 FromDeriveInputFromField 的结构体可以声明名为 identvistyattrsgenerics 的属性,以自动从输入 AST 获取匹配的值的副本。此外,FromDeriveInput 还公开了 data 以获取派生类型主体的访问权限,而 FromVariant 公开了 fields
    • 转发属性转换:您可以将 #[darling(with=path)] 添加到 attrs 字段,以便在将属性提供给您的结构体之前,使用自定义函数转换这些转发属性。该函数签名是 fn(Vec<Attribute>) -> darling::Result<T>,其中 T 是您为 attrs 字段声明的类型。从这个函数返回错误将与其他所有解析错误一起传播。
  • 映射函数:使用 #[darling(map="path")]#[darling(and_then="path")] 来指定一个在解析元项字段的结果上运行的函数。这可以改变返回类型,从而使您能够解析到中间形式并将其转换为您的结构体中所需的类型。
  • 跳过字段:使用 #[darling(skip)] 标记不应从属性元项中读取的字段。
  • 多次出现的字段:在 Vec 字段上使用 #[darling(multiple)] 允许该字段在元项中多次出现。每个出现都将推入 Vec
  • 跨度访问:在结构体中使用 darling::util::SpannedValue 来访问该元项的源代码跨度。这可以用来发出指向您的 proc 宏中特定字段的警告。此外,您还可以使用 darling::Error::write_errors 在大多数情况下自动获取精确的错误位置详细信息。
  • "你可能想"建议:从派生的 darling 特性实现中编译的错误包括对拼写错误的字段的建议。
  • 结构扁平化:使用 #[darling(flatten)] 来在向用户展示元项时移除一层结构。未知于父结构的字段将被转发到 flatten 字段。

形状验证

一些 proc-macros 只在结构体上工作,而另一些需要枚举,其变体为单元或 newtype 变体。Darling 使此类验证变得非常简单。在派生自 FromDeriveInput 的接收器上添加 #[darling(supports(...))],然后列出您的宏应接受的形状。

名称 描述
any 接受任何内容
struct_any 接受任何结构体
struct_named 接受具有命名字段的结构体,例如 struct Example { field: String }
struct_newtype 接受 newtype 结构体,例如 struct Example(String)
struct_tuple 接受元组结构体,例如 struct Example(String, String)
struct_unit 接受单元结构体,例如 struct Example;
enum_any 接受任何枚举
enum_named 接受具有命名字段的枚举变体
enum_newtype 接受 newtype 枚举变体
enum_tuple 接受元组枚举变体
enum_unit 接受单元枚举变体

每个都是可累加的,因此列出 #[darling(supports(struct_any, enum_newtype))] 将接受所有结构体以及任何所有变体都是 newtype 变体的枚举。

这也可以在派生 FromVariant 时使用,无需使用 enum_ 前缀。

依赖项

~280–740KB
~17K SLoC