Skip to content

Commit

Permalink
EnumVariantMeta derive (bevyengine#1972)
Browse files Browse the repository at this point in the history
There are cases where we want an enum variant name. Right now the only way to do that with rust's std is to derive Debug, but this will also print out the variant's fields. This creates the unfortunate situation where we need to manually write out each variant's string name (ex: in bevyengine#1963), which is both boilerplate-ey and error-prone. Crates such as `strum` exist for this reason, but it includes a lot of code and complexity that we don't need.

This adds a dead-simple `EnumVariantMeta` derive that exposes `enum_variant_index` and `enum_variant_name` functions. This allows us to make cases like bevyengine#1963 much cleaner (see the second commit). We might also be able to reuse this logic for `bevy_reflect` enum derives.
  • Loading branch information
cart authored and ostwilkens committed Jul 27, 2021
1 parent 126702f commit 0d34b0e
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 123 deletions.
40 changes: 40 additions & 0 deletions crates/bevy_derive/src/enum_variant_meta.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::modules::{get_modules, get_path};
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput};

pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let variants = match &ast.data {
Data::Enum(v) => &v.variants,
_ => panic!("Expected an enum."),
};

let modules = get_modules(&ast.attrs);
let bevy_util_path = get_path(&modules.bevy_utils);

let generics = ast.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let struct_name = &ast.ident;
let idents = variants.iter().map(|v| &v.ident);
let names = variants.iter().map(|v| v.ident.to_string());
let indices = 0..names.len();

TokenStream::from(quote! {
impl #impl_generics #bevy_util_path::EnumVariantMeta for #struct_name#ty_generics #where_clause {
fn enum_variant_index(&self) -> usize {
match self {
#(#struct_name::#idents {..} => #indices,)*
}
}
fn enum_variant_name(&self) -> &'static str {
static variants: &[&str] = &[
#(#names,)*
];
let index = self.enum_variant_index();
variants[index]
}
}
})
}
6 changes: 6 additions & 0 deletions crates/bevy_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extern crate proc_macro;
mod app_plugin;
mod bevy_main;
mod bytes;
mod enum_variant_meta;
mod modules;
mod render_resource;
mod render_resources;
Expand Down Expand Up @@ -54,3 +55,8 @@ pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
pub fn bevy_main(attr: TokenStream, item: TokenStream) -> TokenStream {
bevy_main::bevy_main(attr, item)
}

#[proc_macro_derive(EnumVariantMeta, attributes(as_crate))]
pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
enum_variant_meta::derive_enum_variant_meta(input)
}
3 changes: 3 additions & 0 deletions crates/bevy_derive/src/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub struct Modules {
pub bevy_render: String,
pub bevy_asset: String,
pub bevy_core: String,
pub bevy_utils: String,
pub bevy_app: String,
}

Expand All @@ -16,6 +17,7 @@ impl Modules {
bevy_asset: format!("{}::asset", name),
bevy_render: format!("{}::render", name),
bevy_core: format!("{}::core", name),
bevy_utils: format!("{}::utils", name),
bevy_app: format!("{}::app", name),
}
}
Expand All @@ -25,6 +27,7 @@ impl Modules {
bevy_asset: "bevy_asset".to_string(),
bevy_render: "bevy_render".to_string(),
bevy_core: "bevy_core".to_string(),
bevy_utils: "bevy_utils".to_string(),
bevy_app: "bevy_app".to_string(),
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_render/src/mesh/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use bevy_ecs::{
};
use bevy_math::*;
use bevy_reflect::TypeUuid;
use bevy_utils::EnumVariantMeta;
use std::{borrow::Cow, collections::BTreeMap};

use crate::pipeline::{InputStepMode, VertexAttribute, VertexBufferLayout};
Expand All @@ -24,7 +25,7 @@ pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;

/// An array where each entry describes a property of a single vertex.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, EnumVariantMeta)]
pub enum VertexAttributeValues {
Float(Vec<f32>),
Int(Vec<i32>),
Expand Down
Loading

0 comments on commit 0d34b0e

Please sign in to comment.