Skip to content

Commit 1576a7a

Browse files
Peternator7Peter Glotfelty
andauthored
Peternator7/fix transparent typo (#421)
* Fix an incorrect refactor on the unifying of the "transparent" code * Support FromString properly as well * Play with references to make transparent work properly with &'static str. * Add a test case --------- Co-authored-by: Peter Glotfelty <[email protected]>
1 parent 23d2952 commit 1576a7a

File tree

7 files changed

+73
-13
lines changed

7 files changed

+73
-13
lines changed

strum/src/additional_attributes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
//!
7777
//! - `transparent`: Signals that the inner field's implementation should be used, instead of generating
7878
//! one for this variant. Only applicable to enum variants with a single field. Compatible with the
79-
//! `AsRefStr`, `Display` and `IntoStaticStr` derive macros.
79+
//! `AsRefStr`, `Display` and `IntoStaticStr` derive macros. Note that `IntoStaticStr` has a few restrictions,
80+
//! the value must be `'static` and `const_into_str` is not supported in combination with `transparent` b/c
81+
//! transparent relies on a call on `From::from(variant)`.
8082
//!
8183
//! - `disabled`: removes variant from generated code.
8284
//!

strum_macros/src/macros/strings/display.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn display_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
2727

2828
if let Some(..) = variant_properties.transparent {
2929
let arm = super::extract_single_field_variant_and_then(name, variant, |tok| {
30-
quote! { ::core::fmt::Display::fmt(#tok, f)}
30+
quote! { ::core::fmt::Display::fmt(#tok, f) }
3131
})
3232
.map_err(|_| non_single_field_variant_error("transparent"))?;
3333

strum_macros/src/macros/strings/from_string.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,29 @@ pub fn from_string_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
5353
return Err(occurrence_error(fst_kw, kw, "default"));
5454
}
5555

56+
default_kw = Some(kw);
57+
default_err_ty = quote! { #strum_module_path::ParseError };
58+
5659
match &variant.fields {
57-
Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {}
60+
Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
61+
default = quote! {
62+
::core::result::Result::Ok(#name::#ident(s.into()))
63+
};
64+
}
65+
Fields::Named(ref f) if f.named.len() == 1 => {
66+
let field_name = f.named.last().unwrap().ident.as_ref().unwrap();
67+
default = quote! {
68+
::core::result::Result::Ok(#name::#ident { #field_name : s.into() } )
69+
};
70+
}
5871
_ => {
5972
return Err(syn::Error::new_spanned(
6073
variant,
6174
"Default only works on newtype structs with a single String field",
6275
))
6376
}
6477
}
65-
default_kw = Some(kw);
66-
default_err_ty = quote! { #strum_module_path::ParseError };
67-
default = quote! {
68-
::core::result::Result::Ok(#name::#ident(s.into()))
69-
};
78+
7079
continue;
7180
}
7281

strum_macros/src/macros/strings/mod.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,26 @@ where
2121

2222
let pattern_and_return = match &variant.fields {
2323
Fields::Unnamed(f) if f.unnamed.len() == 1 => {
24-
let pat = &quote! { field0 };
25-
let ret_val = return_val_fn(pat);
26-
quote! { (ref #pat) => #ret_val }
24+
let ident = &quote! { field0 };
25+
let ref_kw = match f.unnamed.last().unwrap().ty {
26+
syn::Type::Reference(..) => quote! { },
27+
_ => quote! { ref },
28+
};
29+
30+
let ret_val = return_val_fn(ident);
31+
quote! { (#ref_kw #ident) => #ret_val }
2732
}
2833
Fields::Named(f) if f.named.len() == 1 => {
29-
let ident = &quote! { f.named.last().unwrap().ident.as_ref().unwrap() };
34+
let field = f.named.last().unwrap();
35+
let ref_kw = match field.ty {
36+
syn::Type::Reference(..) => quote! { },
37+
_ => quote! { ref },
38+
};
39+
40+
let ident = field.ident.as_ref().unwrap();
41+
let ident = &quote! { #ident };
3042
let ret_val = return_val_fn(ident);
31-
quote! { {ref #ident} => #ret_val }
43+
quote! { { #ref_kw #ident} => #ret_val }
3244
}
3345
_ => return Err(NonSingleFieldEnum),
3446
};

strum_tests/tests/as_ref_str.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ enum Color {
3030
Green(String),
3131
#[strum(transparent)]
3232
Inner(InnerColor),
33+
#[strum(transparent)]
34+
InnerField { inner: InnerColor },
3335
}
3436

3537
#[test]
@@ -59,6 +61,7 @@ fn as_green_str() {
5961
#[test]
6062
fn as_fuchsia_str() {
6163
assert_eq!("Purple", (Color::Inner(InnerColor::Purple)).as_ref());
64+
assert_eq!("Purple", (Color::InnerField { inner: InnerColor::Purple }).as_ref());
6265
}
6366

6467
#[derive(IntoStaticStr)]
@@ -122,6 +125,10 @@ enum Brightness {
122125
},
123126
#[strum(serialize = "Bright")]
124127
BrightWhite,
128+
#[strum(transparent)]
129+
Gray(&'static str),
130+
#[strum(transparent)]
131+
Grey { inner: &'static str }
125132
}
126133

127134
#[test]
@@ -137,6 +144,8 @@ fn brightness_serialize_all() {
137144
assert_eq!("dark_black", <&'static str>::from(Brightness::DarkBlack));
138145
assert_eq!("dim", <&'static str>::from(Brightness::Dim { glow: 0 }));
139146
assert_eq!("Bright", <&'static str>::from(Brightness::BrightWhite));
147+
assert_eq!("Gray", <&'static str>::from(Brightness::Gray("Gray")));
148+
assert_eq!("Grey", <&'static str>::from(Brightness::Grey { inner: "Grey" }));
140149
}
141150

142151
#[derive(IntoStaticStr)]

strum_tests/tests/display.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ fn non_string_default_to_string() {
157157
enum TransparentString {
158158
#[strum(transparent)]
159159
Something(String),
160+
161+
#[strum(transparent)]
162+
SomethingNamed { my_field: String },
160163
}
161164

162165
#[test]
@@ -169,3 +172,16 @@ fn transparent_string() {
169172
)
170173
);
171174
}
175+
176+
#[test]
177+
fn transparent_string_named_field() {
178+
assert_eq!(
179+
String::from("string in here"),
180+
format!(
181+
"{}",
182+
TransparentString::SomethingNamed {
183+
my_field: String::from("string in here")
184+
}
185+
)
186+
);
187+
}

strum_tests/tests/from_str.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ enum Color {
2828
White(String),
2929
}
3030

31+
#[derive(Debug, Eq, PartialEq, EnumString, strum::Display)]
32+
enum Color2 {
33+
#[strum(default)]
34+
Purple { inner: String }
35+
}
36+
3137
#[rustversion::since(1.34)]
3238
fn assert_from_str<'a, T>(a: T, from: &'a str)
3339
where
@@ -74,6 +80,12 @@ fn color_default() {
7480
assert_from_str(Color::Green(String::from("not found")), "not found");
7581
}
7682

83+
#[test]
84+
fn color2_default() {
85+
assert_from_str(Color2::Purple { inner: String::from("test") }, "test");
86+
assert_eq!(String::from("test"), Color2::Purple { inner: String::from("test") }.to_string());
87+
}
88+
7789
#[test]
7890
fn color_ascii_case_insensitive() {
7991
assert_from_str(Color::Black, "BLK");

0 commit comments

Comments
 (0)