add derive Register macro
This commit is contained in:
Generated
+47
@@ -0,0 +1,47 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "pacdef_macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "pacdef_macro"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.49"
|
||||
quote = "1.0.23"
|
||||
syn = "1.0.107"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
@@ -0,0 +1,74 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::DeriveInput;
|
||||
|
||||
#[proc_macro_derive(Register)]
|
||||
pub fn register(input: TokenStream) -> TokenStream {
|
||||
let input = syn::parse::<DeriveInput>(input).unwrap();
|
||||
let name = &input.ident;
|
||||
let enum_data = if let syn::Data::Enum(enum_data) = &input.data {
|
||||
enum_data
|
||||
} else {
|
||||
panic!("`Register` can only be used on enums");
|
||||
};
|
||||
let first_variant = &enum_data.variants[0].ident;
|
||||
|
||||
let variant_matches_backend = enum_data.variants.iter().map(|variant| {
|
||||
let variant_name = &variant.ident;
|
||||
quote! {
|
||||
Self::#variant_name => Box::new(#variant_name::new()),
|
||||
}
|
||||
});
|
||||
|
||||
let variant_matches_next = enum_data.variants.iter().enumerate().map(|(i, variant)| {
|
||||
let variant_name = &variant.ident;
|
||||
if i == enum_data.variants.len() - 1 {
|
||||
quote! {
|
||||
Self::#variant_name => None,
|
||||
}
|
||||
} else {
|
||||
let next_variant = &enum_data.variants[i + 1].ident;
|
||||
quote! {
|
||||
Self::#variant_name => Some(Self::#next_variant),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let variant_imports = enum_data.variants.iter().map(|variant| {
|
||||
let variant_name = &variant.ident;
|
||||
// let variant_module = variant_name.clone();
|
||||
|
||||
let variant_module = proc_macro2::Ident::new(
|
||||
&variant_name.to_string().to_lowercase(),
|
||||
proc_macro2::Span::call_site(),
|
||||
);
|
||||
|
||||
quote! {
|
||||
pub(crate) use #variant_module::#variant_name;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
let expanded = quote! {
|
||||
#(#variant_imports)*
|
||||
|
||||
impl #name {
|
||||
pub fn iter() -> BackendIter {
|
||||
BackendIter {
|
||||
next: Some(Self::#first_variant),
|
||||
}
|
||||
}
|
||||
fn get_backend(&self) -> Box<dyn Backend> {
|
||||
match self {
|
||||
#(#variant_matches_backend)*
|
||||
}
|
||||
}
|
||||
fn next(&self) -> Option<Self> {
|
||||
match self {
|
||||
#(#variant_matches_next)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
Reference in New Issue
Block a user