1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
use proc_macro::TokenStream; use proc_macro2::Span; use quote::quote; #[proc_macro_derive(Std140)] pub fn std140(input: TokenStream) -> TokenStream{ let ast: syn::DeriveInput = syn::parse(input).unwrap(); let ident = ast.ident; let (impl_gen, ty_gen, where_clause) = ast.generics.split_for_impl(); if let syn::Data::Struct(data_struct) = ast.data { let fields = data_struct.fields; match fields{ syn::Fields::Named(fields) => { let field = fields.named.into_iter().map(|f| f.ident); quote!( impl #impl_gen WriteStd140 for #ident #ty_gen #where_clause { fn write_std140(&self, data: &mut Data) { let len = data.bytes(); #(self.#field.write_std140(data);)* let total = data.bytes() - len; let rem = total % 16; if rem != 0 { let padding = 16 - rem; data.pad_bytes(padding); } } } ).into() } _ => syn::Error::new(Span::call_site(), "Std140 can only be implemented for named struct") .to_compile_error() .into() } }else{ panic!("Std140 can only be derived for structs") } }