fn derive_arbitrary()

in shed/quickcheck_arbitrary_derive/src/lib.rs [68:117]


fn derive_arbitrary(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    let DeriveInput {
        ident,
        generics,
        data,
        ..
    } = match syn::parse2(input) {
        Ok(input) => input,
        Err(err) => return err.to_compile_error(),
    };

    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    let implem = match data {
        syn::Data::Struct(data) => {
            let fields = generate_arbitrary_fields(data.fields);
            quote::quote! { Self #fields }
        }
        syn::Data::Enum(data) => {
            if data.variants.is_empty() {
                return syn::Error::new(ident.span(), EMPTY_ENUMS_DISALLOWED).into_compile_error();
            }
            let arbitraries = data.variants.into_iter().map(|variant| {
                let variant_ident = variant.ident;
                let variant_fields = generate_arbitrary_fields(variant.fields);
                quote::quote! { Self :: #variant_ident #variant_fields }
            });

            let variant_indices = (0..arbitraries.len()).map(syn::Index::from);
            let num_variants = syn::Index::from(arbitraries.len());
            quote::quote! {
                match g.choose((0..#num_variants).collect::<Vec<_>>().as_slice()) {
                    #(Some(&#variant_indices) => #arbitraries,)*
                    _ => unreachable!("You encountered a bug within the `quickcheck_arbitrary_derive` crate. Please report it back to the maintainers. Thank you! :)"),
                }
            }
        }
        syn::Data::Union(_) => {
            return syn::Error::new(ident.span(), UNTAGGED_UNIONS_DISALLOWED).into_compile_error();
        }
    };

    quote::quote! {
        impl #impl_generics quickcheck::Arbitrary for #ident #ty_generics #where_clause {
            fn arbitrary(g: &mut quickcheck::Gen) -> Self {
                #implem
            }
        }
    }
}