Skip to main content

enum_display_style_derive/
lib.rs

1mod macro_models;
2
3use crate::macro_models::DisplayStyleArgs;
4use darling::FromVariant;
5use quote::quote;
6use syn::{Data, DeriveInput, parse_macro_input};
7
8/// Derive macro for generating a `to_display_str` method for an enum.
9///
10/// # Example
11///
12/// Using default values for the display style:
13///
14/// ```
15/// use enum_display_style_derive::EnumDisplayStyle;
16///
17/// #[derive(EnumDisplayStyle)]
18/// enum Weekend {
19///     Saturday,
20///     Sunday,
21/// }
22///
23/// assert_eq!(Weekend::Saturday.to_display_str(), "Saturday");
24/// assert_eq!(Weekend::Sunday.to_display_str(), "Sunday");
25/// ```
26///
27/// Using custom values for the display style:
28///
29/// ```
30/// use enum_display_style_derive::EnumDisplayStyle;
31///
32/// #[derive(EnumDisplayStyle)]
33/// enum MonitorStatus {
34///     #[display_style(name = "Monitor Transactions")]
35///     Active,
36///     #[display_style(name = "Don't Monitor Transactions")]
37///     None,
38/// }
39///
40/// assert_eq!(MonitorStatus::Active.to_display_str(), "Monitor Transactions");
41/// assert_eq!(MonitorStatus::None.to_display_str(), "Don't Monitor Transactions");
42/// ```
43#[proc_macro_derive(EnumDisplayStyle, attributes(display_style))]
44pub fn enum_display_style_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
45  let input = parse_macro_input!(input as DeriveInput);
46  let enum_name = &input.ident;
47
48  let mut match_arms = Vec::new();
49
50  if let Data::Enum(data_enum) = &input.data {
51    let variants = &data_enum.variants;
52
53    for variant in variants {
54      let variant_ident = &variant.ident;
55      let variant_display_name = DisplayStyleArgs::from_variant(variant)
56        .unwrap()
57        .name
58        .unwrap_or_else(|| variant_ident.to_string());
59
60      match_arms.push(quote! {
61        #enum_name::#variant_ident => #variant_display_name,
62      });
63    }
64  }
65
66  quote! {
67    impl<'a> #enum_name {
68      pub fn to_display_str(self) -> &'a str {
69        match self {
70          #(#match_arms)*
71        }
72      }
73    }
74  }
75  .into()
76}