use proc_macro2::Ident;
use quote::ToTokens;
use syn::Type;
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(rand_gen), supports(struct_any))]
pub(crate) struct RandGenReceiver {
ident: syn::Ident,
generics: syn::Generics,
data: darling::ast::Data<(), RandGenField>,
}
impl ToTokens for RandGenReceiver {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let RandGenReceiver {
ref ident,
ref generics,
ref data,
} = *self;
let (imp, ty, wher) = generics.split_for_impl();
let fields = data
.as_ref()
.take_struct()
.expect("Should never be enum")
.fields;
let result = fields.iter().map(|x| {
let ident = x.ident.clone();
let ty = x.ty.clone();
let code = match x.method.clone() {
Some(method) => quote! {#method(rng)},
None => {
quote! {
#ty::random(rng)
}
}
};
quote! {
#ident: #code
}
});
tokens.extend(quote! {
impl #imp RandGen for #ident #ty #wher {
fn random<R: Rng + ?Sized>(rng: &mut R) -> Self {
Self {
#(#result),*
}
}
}
});
}
}
#[derive(Debug, FromField)]
#[darling(attributes(rand_gen))]
pub(crate) struct RandGenField {
ident: Option<syn::Ident>,
ty: Type,
method: Option<Ident>, }