Announcing darling 0.1 for proc macro authors


#1

Darling is a proc macro for writing proc macros. Short for “Declarative Attributes for Rust LINGua”, darling provides a serde-inspired API for reading attributes and fields into structs chosen by the proc-macro author.

Usage

This example is taken from from_variants, which generates From impls for newtype enum variants.

#[derive(FromDeriveInput)]
#[darling(from_ident, attributes(from_variants))]
pub struct Context {
    pub into: bool,
    pub ident: syn::Ident,
    generics: syn::Generics,
    body: Body<Variant, Field>,
}

impl From<syn::Ident> for Context {
    fn from(ident: syn::Ident) -> Self {
        Context {
            ident,
            into: false,
            generics: Default::default(),
            body: Body::Enum(vec![]),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, FromVariant)]
#[darling(from_ident, attributes(from_variants), map = "Self::validate")]
pub struct Variant {
    ident: syn::Ident,
    skip: Option<bool>,
    into: Option<bool>,
    data: VariantData<syn::Ty>,
}

impl Variant {
    fn validate(self) -> Self {
        if self.is_enabled() && !self.data.is_newtype() {
            panic!("Variants must be newtype or unit");
        }

        self
    }
    
    /// Check if this variant will emit a converter.
    pub fn is_enabled(&self) -> bool {
        !(self.data.is_unit() || self.skip.unwrap_or(false))
    }
}

To Do

  • Need to finalize the error strategy; at the moment it’s just a wrapper around a string.
  • Add more tests
  • More documentation

#2

Update; darling is now on v0.2.0. The main changes are:

  1. Error strategy is now “finalized” at a high level. Errors are created using static methods (like in serde), and the internal representation is opaque. This will allow adding more error cases in the future without breaking compatibility.
  2. Errors are collected throughout parsing, and returned at the end. This enables proc-macro crates to pass all errors back to the consuming crate author from a single check/build, rather than requiring repeated builds (hat-tip to serde on the inspiration for how to achieve this)
  3. FromMetaItem can now be derived on any struct or enum variant shape except multi-element tuples.
  4. More built-in FromMetaItem impls for std and syn types.
  5. Support for accumulating repeated meta-item declarations into a single Vec

#3

Just in case you don’t know, there already is a well-known project named Darling.


#4

I wasn’t aware of that; thanks for pointing it out. Since there are already a few crates depending on it under the current name, I’m not sure how much room I have to make changes, but I’ll reach out to the elder darling.


#5

… I’m one of its developers, by the way.