limelight-derive 0.1.0

Derive macro for limelight
Documentation
extern crate proc_macro;

use proc_macro2::TokenStream;
use quote::quote;
use syn::ItemStruct;

#[proc_macro_attribute]
pub fn vertex_attribute(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let item: TokenStream = item.into();
    
    let r = quote! {
        #[repr(C)]
        #[derive(Clone, Copy, limelight::VertexAttribute, limelight::bytemuck::Pod, limelight::bytemuck::Zeroable)]
        #item
    };

    r.into()
}

#[proc_macro_derive(VertexAttribute)]
pub fn vertex_attribute_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    impl_vertex_attribute_derive(input.into()).into()
}

fn bind(field: &syn::Field) -> TokenStream {
    let name = field.ident.as_ref().unwrap().to_string();
    let kind = &field.ty;

    quote! {
        limelight::VertexAttributeBinding {
            variable_name: (#name).to_string(),
            kind: <#kind as limelight::types::AsSizedDataType>::as_sized_data_type(),
        }
    }
}

fn impl_vertex_attribute_derive(input: TokenStream) -> TokenStream {
    let ast: ItemStruct = syn::parse2(input).expect("Should decorate a struct.");

    let name = &ast.ident;

    let bindings: Vec<TokenStream> = match &ast.fields {
        syn::Fields::Named(fields) => fields.named.iter().map(bind).collect(),
        _ => panic!("Only structs with named fields can derive StateMachine currently."),
    };

    quote! {
        impl limelight::VertexAttribute for #name {
            fn describe() -> Vec<limelight::VertexAttributeBinding> {
                vec![
                    #(#bindings),*
                ]
            }
        }
    }
}