use syn::{Error, LitInt, Result, DeriveInput, Token};
use proc_macro::TokenStream;
use quote::quote;
pub struct SizeAlign {
pub size: usize,
pub align: usize,
}
impl syn::parse::Parse for SizeAlign {
fn parse(input: syn::parse::ParseStream) -> Result<Self> {
let mut size = None;
let mut align = None;
while !input.is_empty() {
let field_name: syn::Ident = input.parse()?; input.parse::<Token![:]>()?;
match field_name.to_string().as_str() {
"size" => {
let value: LitInt = input.parse()?; size = Some(value.base10_parse::<usize>()?); }
"align" => {
let value: LitInt = input.parse()?; align = Some(value.base10_parse::<usize>()?); }
_ => return Err(Error::new(field_name.span(), "Unexpected field")), }
if input.is_empty() {
break;
}
input.parse::<Token![,]>()?; }
Ok(SizeAlign { size: size.ok_or_else(|| Error::new(input.span(), "Missing field `size`"))?,
align: align.ok_or_else(|| Error::new(input.span(), "Missing field `align`"))?,
})
}
}
pub fn assert_align_size_impl(size: usize, align: usize, input: &DeriveInput) -> TokenStream {
let name = &input.ident;
let generated_code = quote! {
#input
const _: () = {
const _: [(); ::core::mem::size_of::<#name>()] = [(); #size]; const _: [(); ::core::mem::align_of::<#name>()] = [(); #align]; };
};
generated_code.into()
}