From 63ee822851d45d1763145a730138ada1e41d254b Mon Sep 17 00:00:00 2001 From: Vladimir Date: Sun, 10 Mar 2024 21:30:56 +0300 Subject: [PATCH] feat(as_ref_str): enable `prefix` attribute for `AsRefStr` derive (#334) * feat(as_ref_str): enable `prefix` attribute for `AsRefStr` derive * doc(as_ref_str): add prefix example --- strum_macros/src/helpers/variant_props.rs | 16 +++++++++++++--- strum_macros/src/lib.rs | 12 ++++++++++++ strum_macros/src/macros/enum_variant_names.rs | 3 ++- strum_macros/src/macros/strings/as_ref_str.rs | 4 +++- strum_macros/src/macros/strings/display.rs | 6 ++---- strum_macros/src/macros/strings/to_string.rs | 3 ++- strum_tests/tests/prefix.rs | 4 +++- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/strum_macros/src/helpers/variant_props.rs b/strum_macros/src/helpers/variant_props.rs index d6e0cab3..681c7c06 100644 --- a/strum_macros/src/helpers/variant_props.rs +++ b/strum_macros/src/helpers/variant_props.rs @@ -30,14 +30,24 @@ impl StrumVariantProperties { LitStr::new(&ident.convert_case(case_style), ident.span()) } - pub fn get_preferred_name(&self, case_style: Option) -> LitStr { - self.to_string.as_ref().cloned().unwrap_or_else(|| { + pub fn get_preferred_name( + &self, + case_style: Option, + prefix: Option<&LitStr>, + ) -> LitStr { + let mut output = self.to_string.as_ref().cloned().unwrap_or_else(|| { self.serialize .iter() .max_by_key(|s| s.value().len()) .cloned() .unwrap_or_else(|| self.ident_as_str(case_style)) - }) + }); + + if let Some(prefix) = prefix { + output = LitStr::new(&(prefix.value() + &output.value()), output.span()); + } + + output } pub fn get_serializations(&self, case_style: Option) -> Vec { diff --git a/strum_macros/src/lib.rs b/strum_macros/src/lib.rs index 11a1cd7b..c653d4a3 100644 --- a/strum_macros/src/lib.rs +++ b/strum_macros/src/lib.rs @@ -155,6 +155,18 @@ pub fn from_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream { /// Color::Blue(10).as_ref(), /// Color::Green { range: 42 }.as_ref() /// ); +/// +/// // With prefix on all variants +/// #[derive(AsRefStr, Debug)] +/// #[strum(prefix = "/")] +/// enum ColorWithPrefix { +/// #[strum(serialize = "redred")] +/// Red, +/// Green, +/// } +/// +/// assert_eq!("/redred", ColorWithPrefix::Red.as_ref()); +/// assert_eq!("/Green", ColorWithPrefix::Green.as_ref()); /// ``` #[proc_macro_derive(AsRefStr, attributes(strum))] pub fn as_ref_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream { diff --git a/strum_macros/src/macros/enum_variant_names.rs b/strum_macros/src/macros/enum_variant_names.rs index f53b0afa..8c41cc44 100644 --- a/strum_macros/src/macros/enum_variant_names.rs +++ b/strum_macros/src/macros/enum_variant_names.rs @@ -22,7 +22,8 @@ pub fn enum_variant_names_inner(ast: &DeriveInput) -> syn::Result { .iter() .map(|v| { let props = v.get_variant_properties()?; - Ok(props.get_preferred_name(type_properties.case_style)) + Ok(props + .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref())) }) .collect::>>()?; diff --git a/strum_macros/src/macros/strings/as_ref_str.rs b/strum_macros/src/macros/strings/as_ref_str.rs index 617b8879..8d44f810 100644 --- a/strum_macros/src/macros/strings/as_ref_str.rs +++ b/strum_macros/src/macros/strings/as_ref_str.rs @@ -25,7 +25,9 @@ fn get_arms(ast: &DeriveInput) -> syn::Result> { // Look at all the serialize attributes. // Use `to_string` attribute (not `as_ref_str` or something) to keep things consistent // (i.e. always `enum.as_ref().to_string() == enum.to_string()`). - let output = variant_properties.get_preferred_name(type_properties.case_style); + let output = variant_properties + .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref()); + let params = match variant.fields { Fields::Unit => quote! {}, Fields::Unnamed(..) => quote! { (..) }, diff --git a/strum_macros/src/macros/strings/display.rs b/strum_macros/src/macros/strings/display.rs index 47432f5e..a2f6f24a 100644 --- a/strum_macros/src/macros/strings/display.rs +++ b/strum_macros/src/macros/strings/display.rs @@ -24,10 +24,8 @@ pub fn display_inner(ast: &DeriveInput) -> syn::Result { } // Look at all the serialize attributes. - let mut output = variant_properties.get_preferred_name(type_properties.case_style); - if let Some(prefix) = &type_properties.prefix { - output = LitStr::new(&(prefix.value() + &output.value()), output.span()); - } + let output = variant_properties + .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref()); let params = match variant.fields { Fields::Unit => quote! {}, diff --git a/strum_macros/src/macros/strings/to_string.rs b/strum_macros/src/macros/strings/to_string.rs index 9a1e6617..6d440688 100644 --- a/strum_macros/src/macros/strings/to_string.rs +++ b/strum_macros/src/macros/strings/to_string.rs @@ -39,7 +39,8 @@ pub fn to_string_inner(ast: &DeriveInput) -> syn::Result { } // Look at all the serialize attributes. - let output = variant_properties.get_preferred_name(type_properties.case_style); + let output = variant_properties + .get_preferred_name(type_properties.case_style, type_properties.prefix.as_ref()); let params = match variant.fields { Fields::Unit => quote! {}, diff --git a/strum_tests/tests/prefix.rs b/strum_tests/tests/prefix.rs index 806b5d52..ca394dde 100644 --- a/strum_tests/tests/prefix.rs +++ b/strum_tests/tests/prefix.rs @@ -1,7 +1,8 @@ use strum::{Display, EnumString}; +use strum_macros::AsRefStr; #[allow(dead_code)] -#[derive(Debug, EnumString, Display)] +#[derive(Debug, EnumString, Display, AsRefStr)] #[strum(prefix = "colour/")] enum Color { #[strum(to_string = "RedRed")] @@ -17,4 +18,5 @@ enum Color { #[test] fn prefix_redred() { assert_eq!(String::from("colour/RedRed"), (Color::Red).to_string()); + assert_eq!(("colour/RedRed"), (Color::Red).as_ref()); }