use crate::tests::*;
use proptest::prelude::*;
use quote::{format_ident, quote};
#[derive(Debug)]
pub(crate) struct Struct {
pub name: String,
pub fields: Vec<Field>,
}
impl Struct {
pub fn includes_not_ordered_ty(&self) -> bool {
self.fields.iter().any(|f| !f.is_ordered_ty())
}
}
impl Arbitrary for Struct {
type Parameters = (Target, u8);
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with((target, deep): (Target, u8)) -> Self::Strategy {
prop::collection::vec(Field::arbitrary_with((target, deep + 1)), 1..20)
.prop_map(move |fields| Struct {
name: gen_name(true),
fields,
})
.boxed()
}
}
impl Generate for Struct {
type Options = Target;
fn declaration(&self, target: Target) -> TokenStream {
let name = format_ident!("{}", self.name);
let fields = self
.fields
.iter()
.map(|f| f.declaration(()))
.collect::<Vec<TokenStream>>();
let mc = match target {
Target::Block => quote! {
#[block]
#[derive(Debug)]
#[allow(non_snake_case, non_camel_case_types)]
},
Target::Payload => {
let payload_macro = if self.includes_not_ordered_ty() {
quote! {
#[payload(bincode, no_crc)]
}
} else {
quote! {
#[payload(bincode)]
}
};
quote! {
#payload_macro
#[derive(serde::Deserialize, serde::Serialize, Debug)]
#[allow(non_snake_case, non_camel_case_types)]
}
}
};
quote! {
#mc
pub struct #name {
#(#fields,)*
}
}
}
fn instance(&self, _: Target) -> TokenStream {
let name = format_ident!("{}", self.name);
let fields = self
.fields
.iter()
.map(|f| f.instance(()))
.collect::<Vec<TokenStream>>();
quote! {
#name {
#(#fields,)*
}
}
}
}