Repository: Peternator7/strum
Pull request #334 (2024-02-17 19:27:34)

feat(as_ref_str): enable `prefix` attribute for `AsRefStr` derive
Enable `prefix` attribute for `AsRefStr` derive so

> (i.e. always `enum.as_ref().to_string() == enum.to_string()`).

Is true again

seanpianka: Is this PR related to some bug in #296?

Patch:
diff --git a/strum_macros/src/helpers/variant_props.rs b/strum_macros/src/helpers/variant_props.rs
index d6e0cab..681c7c0 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<CaseStyle>) -> LitStr {
-        self.to_string.as_ref().cloned().unwrap_or_else(|| {
+    pub fn get_preferred_name(
+        &self,
+        case_style: Option<CaseStyle>,
+        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<CaseStyle>) -> Vec<LitStr> {
diff --git a/strum_macros/src/lib.rs b/strum_macros/src/lib.rs
index 11a1cd7..c653d4a 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_try_as.rs b/strum_macros/src/macros/enum_try_as.rs
index 1efbbe8..c6d0127 100644
--- a/strum_macros/src/macros/enum_try_as.rs
+++ b/strum_macros/src/macros/enum_try_as.rs
@@ -10,6 +10,7 @@ pub fn enum_try_as_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
     };
 
     let enum_name = &ast.ident;
+    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
 
     let variants: Vec<_> = variants
         .iter()
@@ -72,9 +73,8 @@ pub fn enum_try_as_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
         .collect();
 
     Ok(quote! {
-        impl #enum_name {
+        impl #impl_generics #enum_name #ty_generics #where_clause {
             #(#variants)*
         }
-    }
-    .into())
+    })
 }
diff --git a/strum_macros/src/macros/enum_variant_names.rs b/strum_macros/src/macros/enum_variant_names.rs
index f53b0af..8c41cc4 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<TokenStream> {
         .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::<syn::Result<Vec<LitStr>>>()?;
 
diff --git a/strum_macros/src/macros/strings/as_ref_str.rs b/strum_macros/src/macros/strings/as_ref_str.rs
index 617b887..8d44f81 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<Vec<TokenStream>> {
         // 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 47432f5..a2f6f24 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<TokenStream> {
         }
 
         // 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 9a1e661..6d44068 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<TokenStream> {
         }
 
         // 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! {},


Test patch:
diff --git a/strum_tests/tests/prefix.rs b/strum_tests/tests/prefix.rs
index 806b5d5..ca394dd 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());
 }