fn gen_struct_new_fuzzed_impl()

in lain_derive/src/new_fuzzed_old.rs [255:364]


fn gen_struct_new_fuzzed_impl(
    name: &syn::Ident,
    fields: &[FuzzerObjectStructField],
) -> TokenStream {
    let mut generate_arms = vec![];
    let mut generate_linear = vec![];

    for (i, f) in fields.iter().enumerate() {
        let span = f.field.span();
        let ty = &f.field.ty;

        let mut field_mutation_tokens = TokenStream::new();
        let ident = &f.field.ident;

        // If the field is ignored, return the default value
        if f.ignore {
            field_mutation_tokens.extend(quote_spanned! { span =>
                let value = <#ty>::default();
            });
        }
        // If the user supplied an initializer, use that
        else if let Some(ref initializer) = f.user_initializer {
            field_mutation_tokens.extend(quote_spanned! { span =>
                let value = #initializer;
            });
        } else {
            // Otherwise, we assume that the field implements NewFuzzed and
            // we generate that value here

            let weighted = &f.weighted;

            let default_constraints = if f.min.is_some() || f.max.is_some() {
                let min = f
                    .min
                    .as_ref()
                    .map(|v| quote! {Some(#v)})
                    .unwrap_or_else(|| quote! {None});
                let max = f
                    .max
                    .as_ref()
                    .map(|v| quote! {Some(#v)})
                    .unwrap_or_else(|| quote! {None});

                quote_spanned! { span =>
                    let mut constraints = Constraints::new();
                    constraints.min = #min;
                    constraints.max = #max;
                    constraints.max_size = max_size.clone();
                    constraints.weighted = #weighted;
                    constraints.base_object_size_accounted_for = true;

                    let constraints = Some(constraints);
                }
            } else {
                quote_spanned! { span =>
                    let constraints = max_size.and_then(|max|{
                        let mut c = ::lain::types::Constraints::new();
                        c.base_object_size_accounted_for = true;
                        c.max_size(max);

                        Some(c)
                    });
                }
            };

            field_mutation_tokens.extend(quote_spanned! { span =>
                #default_constraints
                let value = <#ty>::new_fuzzed(mutator, constraints.as_ref());
            });
        }

        let ident_string = ident.as_ref().unwrap().to_string();
        field_mutation_tokens.extend(quote! {

        });

        generate_linear.push(field_mutation_tokens.clone());

        generate_arms.push(quote! {
            #i => {
                #field_mutation_tokens
            }
        });
    }

    let generate_fields_count = generate_arms.len();

    quote! {

        if Self::is_variable_size() {
            // this makes for ugly code generation, but better perf
            for i in sample(&mut mutator.rng, #generate_fields_count, #generate_fields_count).iter() {
                match i {
                    #(#generate_arms)*
                    _ => unreachable!(),
                }
            }
        } else {
            #(#generate_linear)*
        }

        let mut initialized_struct = unsafe { uninit_struct.assume_init() };

        if mutator.should_fixup() {
            initialized_struct.fixup(mutator);
        }

        initialized_struct
    }
}