diff options
Diffstat (limited to 'util-macros')
| -rw-r--r-- | util-macros/src/lib.rs | 51 | 
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() +}  | 
