Darling: parse list of identifiers

My initial goal was to add a field attribute that looks like this:

#[my_attribute(some_identifier, other_identifier)]
my_field: i32

I decided to use darling as I discovered it recently and already used it in some places and it was great.
First I tried `#[darling(multiple)]' but it actually works like this:

#[my_attribute = some_identifier, my_attribute = other_identifier)]
my_field: i32

I ended up with this code:

#[derive(Debug, Clone)]
struct IdentList(Vec<Ident>);
impl Parse for IdentList {
    fn parse(input: ParseStream) -> Result<Self> {
        let punctuated = Punctuated::<Ident, Comma>::parse_terminated(input)?;
        Ok(IdentList(punctuated.into_iter().collect()))
    }
}

impl FromMeta for IdentList {
    fn from_meta(item: &Meta) -> darling::Result<Self> {
        syn::parse2::<IdentList>(item.require_list()?.tokens.clone())
            .map_err(|e| darling::Error::custom(e))
    }
}

#[derive(FromField, Debug, Clone)]
#[darling(attributes(my_attribute))]
struct FieldOpts {
    #[darling(default)]
    my_list: Option<IdentList>,
}

which allows such attributes: #[my_attribute(my_list(ident0, ident1))].

But I feel like I missed something or have done something in a more complicated way than it is possible.

I suggest you use Deluxe instead, which offers a number of usability improvements over Darling. The link I just posted points to the relevant section in the docs – tuple structs can be parsed as parenthesis-enclosed lists.

If you are after some more advanced, customizable yet still derive-able parsers, you can also try my crate Parsel.

4 Likes