genesis-impl 0.2.2

proc macro crate for genesis
Documentation
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};

use crate::input::*;

pub(crate) fn generate_code(input: &Input) -> TokenStream {
    let enum_definition = generate_enum_definition(input);
    let from_impls = generate_from_impls(input);

    let extra_attributes = input.attributes.iter().map(|attr| {
        let tokens = &attr.to_token_stream();
        quote! {
            #tokens
        }
    });

    quote! {
        #(#extra_attributes)*
        #enum_definition
        #from_impls
    }
}

fn generate_enum_definition(input: &Input) -> TokenStream {
    let component_fields = input.components.iter().map(|c| {
        let ty = &c.field.ty;
        quote! {
            #ty(#ty),
        }
    });

    let vis = &input.vis;
    let name = &input.component_enum_name;

    quote! {
        #vis enum #name {
            #(#component_fields)*
        }
    }
}

fn generate_from_impls(input: &Input) -> TokenStream {
    let component_enum = &input.component_enum_name;
    let from_impls = input.components.iter().map(|c| {
        let ty = &c.field.ty;
        quote! {
            impl From<#ty> for #component_enum {
                fn from(component: #ty) -> Self {
                    Self::#ty(component)
                }
            }
        }
    });

    quote! {
        #(#from_impls)*
    }
}