Skip to content

Commit

Permalink
Relax Ident constraint to allow all valid strings for argument values (
Browse files Browse the repository at this point in the history
…#39)

Hey Yago!

I've been using `enum_stringify` a lot lately for my 8086 decoder
project. It saves me a lot of boilerplate code and prevents the need to
write my own macro. Thank you!

However, I came across a few limitations. If the argument value for
`rename`, `prefix`, or `suffix` is not a valid identifier pattern, the
macro panics, causing a compilation failure. For example, this causes a
compilation failure:

```rust
#[derive(enum_stringify::EnumStringify)]
enum Separator {
    #[enum_stringify(rename = " ")]
    Space,
    #[enum_stringify(rename = "-")]
    Hyphen,
    #[enum_stringify(rename = "")]
    Empty,
}
```
It appears that these argument values are constrained to fit the Ident
pattern, which reduces flexibility by disallowing valid string literals.
This PR addresses the issue.

Please take a look and let me know what you think.
  • Loading branch information
Yag000 authored Jun 14, 2024
2 parents 63a7739 + 433b0c0 commit 2880b02
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 8 deletions.
6 changes: 3 additions & 3 deletions src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,12 @@ impl Attributes {
self.variant_renames.insert(variant.ident.clone(), rename);
}

pub(crate) fn apply(&self) -> Vec<(syn::Ident, syn::Ident)> {
pub(crate) fn apply(&self) -> Vec<(syn::Ident, String)> {
let mut new_names = Vec::new();

for (name, rename) in &self.variant_renames {
if let Some(rename) = rename {
new_names.push(syn::Ident::new(&rename.0, name.span()));
new_names.push(rename.0.clone());
continue;
}
let mut new_name = String::new();
Expand All @@ -241,7 +241,7 @@ impl Attributes {
};
}

new_names.push(syn::Ident::new(&new_name, name.span()));
new_names.push(new_name);
}

let tmp = self
Expand Down
10 changes: 5 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ fn impl_enum_to_string(ast: &syn::DeriveInput) -> TokenStream {
let coplues = attributes.apply();

let identifiers: Vec<&syn::Ident> = coplues.iter().map(|(i, _)| i).collect();
let names: Vec<syn::Ident> = coplues.iter().map(|(_, n)| n.clone()).collect();
let names: Vec<String> = coplues.iter().map(|(_, n)| n.clone()).collect();

let mut gen = impl_display(name, &identifiers, &names);
gen.extend(impl_from_str(name, &identifiers, &names));
Expand All @@ -186,13 +186,13 @@ fn impl_enum_to_string(ast: &syn::DeriveInput) -> TokenStream {
fn impl_display(
name: &syn::Ident,
identifiers: &Vec<&syn::Ident>,
names: &Vec<syn::Ident>,
names: &Vec<String>,
) -> TokenStream {
let gen = quote! {
impl ::std::fmt::Display for #name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
#(Self::#identifiers=> write!(f, stringify!(#names))),*
#(Self::#identifiers=> write!(f, #names)),*
}
}
}
Expand All @@ -205,15 +205,15 @@ fn impl_display(
fn impl_from_str(
name: &syn::Ident,
identifiers: &Vec<&syn::Ident>,
names: &Vec<syn::Ident>,
names: &Vec<String>,
) -> TokenStream {
let gen = quote! {
impl TryFrom<&str> for #name {
type Error = ();

fn try_from(s: &str) -> Result<Self, Self::Error> {
match s {
#(stringify!(#names) => Ok(Self::#identifiers),)*
#(#names => Ok(Self::#identifiers),)*
_ => Err(()),
}
}
Expand Down
25 changes: 25 additions & 0 deletions tests/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,28 @@ fn test_double_rename_from_str() {
Ok(DoubleAniurRename::Maiar)
);
}

#[derive(PartialEq, Debug, enum_stringify::EnumStringify)]
enum Seperator {
#[enum_stringify(rename = " ")]
Space,
#[enum_stringify(rename = "-")]
Hyphen,
#[enum_stringify(rename = "")]
Empty,
}

#[test]
fn test_seperator_rename() {
assert_eq!(Seperator::Space.to_string(), " ");
assert_eq!(Seperator::Hyphen.to_string(), "-");
assert_eq!(Seperator::Empty.to_string(), "");
}

#[test]
fn test_seperator_rename_from_str() {
assert_eq!(Seperator::from_str(" "), Ok(Seperator::Space));
assert_eq!(Seperator::from_str("-"), Ok(Seperator::Hyphen));
assert_eq!(Seperator::from_str(""), Ok(Seperator::Empty));
assert!(Seperator::from_str("|").is_err());
}

0 comments on commit 2880b02

Please sign in to comment.