limelight_derive/
lib.rs

1extern crate proc_macro;
2
3use proc_macro2::TokenStream;
4use quote::quote;
5use syn::ItemStruct;
6
7#[proc_macro_attribute]
8pub fn attribute(
9    _attr: proc_macro::TokenStream,
10    item: proc_macro::TokenStream,
11) -> proc_macro::TokenStream {
12    let item: TokenStream = item.into();
13
14    let r = quote! {
15        #[repr(C)]
16        #[derive(Clone, Copy, limelight::Attribute, limelight::bytemuck::Pod, limelight::bytemuck::Zeroable)]
17        #item
18    };
19
20    r.into()
21}
22
23#[proc_macro_derive(Attribute)]
24pub fn vertex_attribute_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
25    impl_vertex_attribute_derive(input.into()).into()
26}
27
28fn bind(field: &syn::Field) -> TokenStream {
29    let name = field.ident.as_ref().unwrap().to_string();
30    let kind = &field.ty;
31
32    quote! {
33        limelight::AttributeBinding {
34            variable_name: (#name).to_string(),
35            kind: <#kind as limelight::AsSizedDataType>::as_sized_data_type(),
36        }
37    }
38}
39
40fn impl_vertex_attribute_derive(input: TokenStream) -> TokenStream {
41    let ast: ItemStruct = syn::parse2(input).expect("Should decorate a struct.");
42
43    let name = &ast.ident;
44
45    let bindings: Vec<TokenStream> = match &ast.fields {
46        syn::Fields::Named(fields) => fields.named.iter().map(bind).collect(),
47        _ => panic!("Only structs with named fields can derive StateMachine currently."),
48    };
49
50    quote! {
51        impl limelight::Attribute for #name {
52            fn describe() -> Vec<limelight::AttributeBinding> {
53                vec![
54                    #(#bindings),*
55                ]
56            }
57        }
58    }
59}