#darling #proc-macro-attributes #structs #macro-derive #field #variant #parser

darling_macro

在实现自定义派生时,内部支持将属性读取到结构体中的过程宏库。在您的代码中使用 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日

1809过程宏 中排名

Download history 1440694/week @ 2024-04-16 1473551/week @ 2024-04-23 1352197/week @ 2024-04-30 1396637/week @ 2024-05-07 1493973/week @ 2024-05-14 1475335/week @ 2024-05-21 1604920/week @ 2024-05-28 1643644/week @ 2024-06-04 1672618/week @ 2024-06-11 1587663/week @ 2024-06-18 1625367/week @ 2024-06-25 1468132/week @ 2024-07-02 1644945/week @ 2024-07-09 1663636/week @ 2024-07-16 1667287/week @ 2024-07-23 1690665/week @ 2024-07-30

6,986,796 每月下载量
用于 7,465 个crate(2个直接使用)

MIT 许可证

295KB
6.5K SLoC

Darling

Build Status Latest Version Rustc Version 1.56+

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

优点

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

使用方法

darling 提供了一组可以派生或手动实现的特质。

  1. FromMeta 用于从属性中的元项中提取值。实现可能对许多库都是可重用的,就像 FromStrserde::Deserialize 一样。为原始数据类型、一些 std 类型以及一些 syn 类型提供了特质实现。
  2. FromDeriveInput 由每个依赖 darling 的过程宏crate实现或派生。这是输入解析的根;它获取对目标类型的身份、泛型和可见性的访问,并可以指定哪些属性名称应从输入AST解析或转发。
  3. FromField 由每个依赖于 darling 的 proc-macro crate 实现。从该特性派生的结构体将能够访问字段的标识(如果存在)、类型和可见性。
  4. FromVariant 由每个依赖于 darling 的 proc-macro crate 实现。从该特性派生的结构体将能够访问变体的标识和内容,这些内容可以像任何其他 darling 输入一样进行转换。
  5. FromAttributesFromDeriveInputFromFieldFromVariant 特性的更具体版本。从该特性派生的结构体将获得一个元项提取器和错误收集器,它适用于任何语法元素,包括特性和函数。这对于非 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 来获取对该元项源代码跨度的访问权限。这可以用来发出指向您的过程宏中特定字段的警告。此外,您还可以使用 darling::Error::write_errors 在大多数情况下自动获取精确的错误位置详细信息。
  • “你可能是指”建议:从派生darling特质的实现中编译错误包括对拼写错误的字段的建议。
  • 结构扁平化:使用#[darling(flatten)]在向用户展示元项时删除一层结构。未知于父结构的字段将被转发到flatten字段。

形状验证

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

名称 描述
任何 接受任何东西
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–730KB
~17K SLoC