-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add IterableEnum
trait
#7269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Add IterableEnum
trait
#7269
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
329fc46
Add `IterableEnum`
DasLixou 5eaeca5
Add `#[derive(IterableEnum)]`
DasLixou 6fcc72b
Use BevyManifest
DasLixou 8beb9ad
Implement for `KeyCode`
DasLixou 31ced3b
Merge branch 'main' into iterable-enum
DasLixou 5bf736d
Update crates/bevy_utils/macros/Cargo.toml
DasLixou e29579c
Update crates/bevy_utils/src/iterable_enum.rs
DasLixou 51d0433
Update crates/bevy_utils/macros/src/lib.rs
DasLixou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "bevy_utils_macros" | ||
version = "0.9.0" | ||
edition = "2021" | ||
description = "Derive implementations for bevy_utils" | ||
homepage = "https://bevyengine.org" | ||
repository = "https://github.com/bevyengine/bevy" | ||
license = "MIT OR Apache-2.0" | ||
keywords = ["bevy"] | ||
|
||
[lib] | ||
proc-macro = true | ||
|
||
[dependencies] | ||
syn = { version = "1.0", features = ["full", "parsing", "extra-traits"] } | ||
quote = "1.0" | ||
bevy_macro_utils = { version = "0.9.0", path = "../../bevy_macro_utils" } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use proc_macro::TokenStream; | ||
use quote::{quote, quote_spanned, ToTokens}; | ||
use syn::{__private::Span, spanned::Spanned, DataEnum}; | ||
|
||
use crate::paths; | ||
|
||
pub fn parse_iterable_enum_derive(input: TokenStream) -> TokenStream { | ||
let ast = syn::parse_macro_input!(input as syn::DeriveInput); | ||
|
||
let span = ast.span(); | ||
|
||
let name = &ast.ident; | ||
let generics = &ast.generics; | ||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); | ||
|
||
let get_at = match ast.data { | ||
syn::Data::Enum(d) => get_at_impl(name, span, d), | ||
_ => quote_spanned! { | ||
span => compile_error!("`IterableEnum` can only be applied to `enum`") | ||
}, | ||
}; | ||
|
||
let iterable_enum = paths::iterable_enum_path(); | ||
|
||
quote! { | ||
impl #impl_generics #iterable_enum for #name #ty_generics #where_clause { | ||
#get_at | ||
} | ||
} | ||
.into() | ||
} | ||
|
||
fn get_at_impl(name: impl ToTokens, span: Span, d: DataEnum) -> quote::__private::TokenStream { | ||
let mut arms = quote!(); | ||
let mut index: usize = 0; | ||
|
||
for variant in d.variants { | ||
match variant.fields { | ||
syn::Fields::Unit => { | ||
let ident = variant.ident; | ||
arms = quote! { #arms #index => Some(#name::#ident), }; | ||
index += 1; | ||
} | ||
_ => { | ||
return quote_spanned! { | ||
span => compile_error!("All Fields should be Units!"); | ||
} | ||
.into(); | ||
} | ||
}; | ||
} | ||
|
||
quote! { | ||
#[inline] | ||
fn get_at(index: usize) -> Option<Self> { | ||
match index { | ||
#arms | ||
_ => None, | ||
} | ||
} | ||
} | ||
.into() | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#![forbid(unsafe_code)] | ||
#![warn(missing_docs)] | ||
|
||
use proc_macro::TokenStream; | ||
DasLixou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
mod iterable_enum; | ||
mod paths; | ||
|
||
#[proc_macro_derive(IterableEnum)] | ||
pub fn iterable_enum_derive(input: TokenStream) -> TokenStream { | ||
iterable_enum::parse_iterable_enum_derive(input) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use bevy_macro_utils::BevyManifest; | ||
use quote::format_ident; | ||
|
||
#[inline] | ||
pub(crate) fn bevy_utils_path() -> syn::Path { | ||
BevyManifest::default().get_path("bevy_utils") | ||
} | ||
|
||
#[inline] | ||
pub(crate) fn iterable_enum_path() -> syn::Path { | ||
let mut utils_path = bevy_utils_path(); | ||
utils_path | ||
.segments | ||
.push(format_ident!("IterableEnum").into()); | ||
utils_path | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use std::marker::PhantomData; | ||
|
||
/// A trait for enums to get a `Unit`-enum-field by a `usize` | ||
pub trait IterableEnum: Sized { | ||
/// Gets an `Unit`-enum-field by the given `usize` index | ||
fn get_at(index: usize) -> Option<Self>; | ||
|
||
/// Creates a new [`EnumIterator`] which will numerically return every `Unit` of this enum | ||
#[inline] | ||
fn enum_iter() -> EnumIterator<Self> { | ||
EnumIterator { | ||
accelerator: 0, | ||
phantom: PhantomData, | ||
} | ||
} | ||
} | ||
|
||
/// An iterator over `IterableEnum`s | ||
/// | ||
/// Iterates all `Unit` fields in numeric order | ||
pub struct EnumIterator<E: IterableEnum> { | ||
accelerator: usize, | ||
phantom: PhantomData<E>, | ||
} | ||
|
||
impl<E: IterableEnum> Iterator for EnumIterator<E> { | ||
type Item = E; | ||
|
||
#[inline] | ||
fn next(&mut self) -> Option<Self::Item> { | ||
if let Some(unit) = E::get_at(self.accelerator) { | ||
self.accelerator += 1; | ||
Some(unit) | ||
} else { | ||
None | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a
get_at
, could we not just generate aconst SLICE: &[Self]
in the trait?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty smart idea. I’ll try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we lose the trait altogether and just generate an associated const on the type itself?