mirror of
https://github.com/robbert-vdh/nih-plug.git
synced 2026-07-01 02:36:54 +00:00
Add stable IDs for enum parameters
This commit is contained in:
@@ -7,10 +7,6 @@ pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
|
||||
let struct_name = &ast.ident;
|
||||
let variants = match ast.data {
|
||||
// syn::Data::Struct(syn::DataStruct {
|
||||
// fields: syn::Fields::Named(named_fields),
|
||||
// ..
|
||||
// }) => named_fields,
|
||||
syn::Data::Enum(syn::DataEnum { variants, .. }) => variants,
|
||||
_ => {
|
||||
return syn::Error::new(ast.span(), "Deriving Enum is only supported on enums")
|
||||
@@ -23,6 +19,8 @@ pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
// order, and the names are either just the variant name or a `#[name = "..."]` attribute in
|
||||
// case the name should contain a space.
|
||||
let mut variant_names = Vec::new();
|
||||
// IDs are optional, but they must either be set for all variants or for none of them
|
||||
let mut variant_ids = Vec::new();
|
||||
let mut to_index_tokens = Vec::new();
|
||||
let mut from_index_tokens = Vec::new();
|
||||
for (variant_idx, variant) in variants.iter().enumerate() {
|
||||
@@ -33,6 +31,7 @@ pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
let mut name_attr: Option<String> = None;
|
||||
let mut id_attr: Option<String> = None;
|
||||
for attr in &variant.attrs {
|
||||
if attr.path.is_ident("name") {
|
||||
match attr.parse_meta() {
|
||||
@@ -57,6 +56,45 @@ pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
.into()
|
||||
}
|
||||
};
|
||||
} else if attr.path.is_ident("id") {
|
||||
match attr.parse_meta() {
|
||||
Ok(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(s),
|
||||
..
|
||||
})) => {
|
||||
if id_attr.is_none() {
|
||||
id_attr = Some(s.value());
|
||||
} else {
|
||||
return syn::Error::new(attr.span(), "Duplicate id attribute")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return syn::Error::new(
|
||||
attr.span(),
|
||||
"The id attribute should be a key-value pair with a string argument: #[id = \"foo-bar\"]",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// IDs must either be set for all variants or for none of them
|
||||
match (id_attr, variant_idx == 0, variant_ids.is_empty()) {
|
||||
(Some(id), true, true) | (Some(id), false, false) => {
|
||||
variant_ids.push(id);
|
||||
}
|
||||
(None, _, true) => (),
|
||||
_ => {
|
||||
return syn::Error::new(
|
||||
variant.span(),
|
||||
"ID attributes must either be set for all variants or for none of them",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +108,12 @@ pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
from_index_tokens.push(quote! { #variant_idx => #struct_name::#variant_ident, });
|
||||
}
|
||||
|
||||
let ids_tokens = if variant_ids.is_empty() {
|
||||
quote! { None }
|
||||
} else {
|
||||
quote! { Some(&[#(#variant_ids),*]) }
|
||||
};
|
||||
|
||||
let from_index_default_tokens = variants.first().map(|v| {
|
||||
let variant_ident = &v.ident;
|
||||
quote! { _ => #struct_name::#variant_ident, }
|
||||
@@ -81,6 +125,10 @@ pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
&[#(#variant_names),*]
|
||||
}
|
||||
|
||||
fn ids() -> Option<&'static [&'static str]> {
|
||||
#ids_tokens
|
||||
}
|
||||
|
||||
fn to_index(self) -> usize {
|
||||
match self {
|
||||
#(#to_index_tokens)*
|
||||
|
||||
@@ -3,8 +3,8 @@ use proc_macro::TokenStream;
|
||||
mod enums;
|
||||
mod params;
|
||||
|
||||
/// Derive the `Enum` trait for your simple enum parameters. See `EnumParam` for more information.
|
||||
#[proc_macro_derive(Enum, attributes(name))]
|
||||
/// Derive the `Enum` trait for simple enum parameters. See `EnumParam` for more information.
|
||||
#[proc_macro_derive(Enum, attributes(name, id))]
|
||||
pub fn derive_enum(input: TokenStream) -> TokenStream {
|
||||
enums::derive_enum(input)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user