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
}
}