From ee5aa421f1d17f59fa8ee6df973d510dc02825ab Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 17 Oct 2024 00:19:18 +0200 Subject: feat(util-macros): add VariantArr derive macro --- util-macros/src/lib.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'util-macros/src') 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::(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::()?; + + arr_name = Some(meta.input.parse::()?); + + 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() +} -- cgit v1.2.3-18-g5258