Skip to content

Commit

Permalink
feat(as_ref_str): enable prefix attribute for AsRefStr derive (#334)
Browse files Browse the repository at this point in the history
* feat(as_ref_str): enable `prefix` attribute for `AsRefStr` derive

* doc(as_ref_str): add prefix example
  • Loading branch information
vbrvk committed Mar 10, 2024
1 parent 9b18468 commit 63ee822
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 11 deletions.
16 changes: 13 additions & 3 deletions strum_macros/src/helpers/variant_props.rs
Expand Up @@ -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> {
Expand Down
12 changes: 12 additions & 0 deletions strum_macros/src/lib.rs
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion strum_macros/src/macros/enum_variant_names.rs
Expand Up @@ -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>>>()?;

Expand Down
4 changes: 3 additions & 1 deletion strum_macros/src/macros/strings/as_ref_str.rs
Expand Up @@ -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! { (..) },
Expand Down
6 changes: 2 additions & 4 deletions strum_macros/src/macros/strings/display.rs
Expand Up @@ -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! {},
Expand Down
3 changes: 2 additions & 1 deletion strum_macros/src/macros/strings/to_string.rs
Expand Up @@ -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! {},
Expand Down
4 changes: 3 additions & 1 deletion 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")]
Expand All @@ -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());
}

0 comments on commit 63ee822

Please sign in to comment.