summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util-macros/src/lib.rs51
1 files changed, 50 insertions, 1 deletions
diff --git a/util-macros/src/lib.rs b/util-macros/src/lib.rs
index 83b5f58..654c626 100644
--- a/util-macros/src/lib.rs
+++ b/util-macros/src/lib.rs
@@ -1,6 +1,6 @@
use proc_macro::{TokenStream, TokenTree};
use quote::quote;
-use syn::{parse, Ident, ItemEnum};
+use syn::{parse, Ident, ItemEnum, Token};
/// Subtracts two numbers and calls a given callback macro with the result. Optionally, a
/// additional argument (delimeted) can be given which will also be passed to the
@@ -199,3 +199,52 @@ pub fn from_repr(input: TokenStream) -> TokenStream
}
.into()
}
+
+#[proc_macro_derive(VariantArr, attributes(variant_arr))]
+pub fn variant_arr(input: TokenStream) -> TokenStream
+{
+ let enum_item = parse::<ItemEnum>(input).unwrap();
+
+ let arr_ident_attr = enum_item
+ .attrs
+ .iter()
+ .find(|attr| {
+ attr.path()
+ .get_ident()
+ .is_some_and(|attr_ident| attr_ident == "variant_arr")
+ })
+ .expect("No variant_arr attribute found");
+
+ let mut arr_name = None;
+
+ arr_ident_attr
+ .parse_nested_meta(|meta| {
+ if meta.path.is_ident("name") {
+ meta.input.parse::<Token![=]>()?;
+
+ arr_name = Some(meta.input.parse::<Ident>()?);
+
+ return Ok(());
+ }
+
+ Err(meta.error("Unknown field in variant_arr attribute"))
+ })
+ .unwrap();
+
+ let arr_name = arr_name.expect("Missing field 'name' in variant_arr attribute");
+
+ let variants = enum_item
+ .variants
+ .iter()
+ .map(|variant| variant.ident.clone());
+
+ let enum_ident = enum_item.ident.clone();
+
+ quote! {
+ impl #enum_ident
+ {
+ pub const #arr_name: &[Self] = &[#(Self::#variants,)*];
+ }
+ }
+ .into()
+}