dioxus_switch_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{Data, DeriveInput, Token, parse_macro_input, punctuated::Punctuated};
4
5#[proc_macro_derive(Switch)]
6pub fn switch(input: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(input as DeriveInput);
8    if let Data::Enum(data_enum) = input.data {
9        let switch_ident = input.ident;
10        let match_arms = data_enum.variants.into_iter().map(|variant| {
11            let component = variant.ident;
12            let keys = variant
13                .fields
14                .into_iter()
15                .map(|f| f.ident.expect("expected enum variants to be named"));
16
17            let keys = Punctuated::<_, Token![,]>::from_iter(keys);
18
19            quote! {
20                Self::#component { #keys } => {
21                    rsx! {
22                        #component { #keys }
23                    }
24                }
25            }
26        });
27
28        let match_arms = Punctuated::<_, Token![,]>::from_iter(match_arms);
29
30        let output = quote! {
31            impl Switchable for #switch_ident {
32                fn component(self) -> Element {
33                    match self {
34                        #match_arms
35                    }
36                }
37            }
38        };
39
40        output.into()
41    } else {
42        panic!("switch can only be used on enums");
43    }
44}