-
Hey, coming in hot with another question: Is it possible to do something like the following? #[derive(FromMeta)]
enum Action {
Added,
Renamed,
Deleted,
}
#[derive(FromField)]
struct FieldAttrs {
#[darling(multiple)]
actions: Vec<Action>,
// Automatically extracted by darling
ident: Option<Ident>
}
// Now comes the tricky bit:
struct MyStruct {
#[my_attr(
added(...),
renamed(...),
deleted(...)
)]
my_field: usize,
} Note, that the attribute ( Let me know how (and if) this can be done and also what you think about adding support for this use-case in darling directly. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
This can be done using use darling::{ast::NestedMeta, Error, FromDeriveInput, FromMeta};
#[derive(Debug, FromMeta)]
enum Action {
Added { name: String },
Edited { was: String, is: String },
Removed { was: String },
}
/// Read a list of FromMeta objects, preserving order, and return the results
/// as a `Vec`.
pub fn from_list<T: FromMeta>(list: &syn::Meta) -> darling::Result<Vec<T>> {
match list {
syn::Meta::List(ref value) => {
let items = NestedMeta::parse_meta_list(value.tokens.clone())?;
let mut errors = Error::accumulator();
let mut parsed = Vec::with_capacity(items.len());
for nmi in items {
errors.handle_in(|| {
if let NestedMeta::Meta(mi) = nmi {
// The derived `FromMeta` impl will expect a field name that it should
// ignore, so we provide one that we know is going to be immediately read
// through.
parsed.push(T::from_meta(&syn::parse_quote!(_ignore(#mi)))?);
Ok(())
} else {
Err(Error::unsupported_format("literal"))
}
});
}
errors.finish_with(parsed)
}
syn::Meta::Path(_) => Err(Error::unsupported_format("word").with_span(&list)),
syn::Meta::NameValue(_) => Err(Error::unsupported_format("value").with_span(&list)),
}
}
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(my))]
struct Receiver {
// XXX the `default` here is needed because darling still tries
// to call `<Vec<Action> as FromMeta>::from_none` otherwise.
#[darling(with = from_list, default)]
actions: Vec<Action>,
}
// Example showing it works
fn main() {
eprintln!(
"{:?}",
Receiver::from_derive_input(&syn::parse_quote! {
#[my(
actions(
added(name = "Hi"),
removed( was = "World")
)
)]
struct Example;
})
.unwrap()
);
} |
Beta Was this translation helpful? Give feedback.
This can be done using
darling(with = ...)
.