use crate::types::make_ident;
use proc_macro2::Ident;
use quote::quote;
use syn::parse::Parser;
use syn::{parse_quote, Field, GenericParam, ItemStruct};
pub(crate) fn new_non_pod_struct(id: Ident) -> ItemStruct {
let mut s = parse_quote! {
pub struct #id {
}
};
make_non_pod(&mut s);
s
}
pub(crate) fn make_non_pod(s: &mut ItemStruct) {
s.attrs = vec![parse_quote!(
#[repr(C, packed)]
)];
let generic_type_fields = s
.generics
.params
.iter()
.enumerate()
.filter_map(|(counter, gp)| match gp {
GenericParam::Type(gpt) => {
let id = &gpt.ident;
let field_name = make_ident(&format!("_phantom_{}", counter));
let toks = quote! {
#field_name: ::std::marker::PhantomData<::std::cell::UnsafeCell< #id >>
};
let parser = Field::parse_named;
Some(parser.parse2(toks).unwrap())
}
_ => None,
});
s.fields = syn::Fields::Named(parse_quote! {
{
do_not_attempt_to_allocate_nonpod_types: [*const u8; 0],
_pinned: core::marker::PhantomData<core::marker::PhantomPinned>,
#(#generic_type_fields),*
}
});
}