Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(as_ref_str): enable prefix attribute for AsRefStr derive #334

Merged
merged 2 commits into from Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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());
}