1 use proc_macro2
::TokenStream
;
4 use crate::helpers
::case_style
::CaseStyle
;
5 use helpers
::{extract_meta, CaseStyleHelpers, MetaIteratorHelpers}
;
7 fn get_arms(ast
: &syn
::DeriveInput
) -> Vec
<TokenStream
> {
9 let mut arms
= Vec
::new();
10 let variants
= match ast
.data
{
11 syn
::Data
::Enum(ref v
) => &v
.variants
,
12 _
=> panic
!("This macro only works on Enums"),
15 let type_meta
= extract_meta(&ast
.attrs
);
16 let case_style
= type_meta
17 .find_unique_property("strum", "serialize_all")
18 .map(|style
| CaseStyle
::from(style
.as_ref()));
20 for variant
in variants
{
22 let ident
= &variant
.ident
;
23 let meta
= extract_meta(&variant
.attrs
);
25 if meta
.is_disabled() {
29 // Look at all the serialize attributes.
30 // Use `to_string` attribute (not `as_ref_str` or something) to keep things consistent
31 // (i.e. always `enum.as_ref().to_string() == enum.to_string()`).
32 let output
= if let Some(n
) = meta
.find_unique_property("strum", "to_string") {
35 let mut attrs
= meta
.find_properties("strum", "serialize");
36 // We always take the longest one. This is arbitary, but is *mostly* deterministic
37 attrs
.sort_by_key(|s
| s
.len());
38 if let Some(n
) = attrs
.pop() {
41 ident
.convert_case(case_style
)
45 let params
= match variant
.fields
{
47 Unnamed(..) => quote
! { (..) }
,
48 Named(..) => quote
! { {..}
},
51 arms
.push(quote
! { #name::#ident #params => #output }
);
54 if arms
.len() < variants
.len() {
56 _
=> panic
!("AsRef::<str>::as_ref() or AsStaticRef::<str>::as_static() \
57 called on disabled variant.")
64 pub fn as_ref_str_inner(ast
: &syn
::DeriveInput
) -> TokenStream
{
65 let name
= &ast
.ident
;
66 let (impl_generics
, ty_generics
, where_clause
) = ast
.generics
.split_for_impl();
67 let arms
= get_arms(ast
);
69 impl #impl_generics ::std::convert::AsRef<str> for #name #ty_generics #where_clause {
70 fn as_ref(&self) -> &str {
79 pub enum GenerateTraitVariant
{
84 pub fn as_static_str_inner(
85 ast
: &syn
::DeriveInput
,
86 trait_variant
: GenerateTraitVariant
,
88 let name
= &ast
.ident
;
89 let (impl_generics
, ty_generics
, where_clause
) = ast
.generics
.split_for_impl();
90 let arms
= get_arms(ast
);
92 let mut generics
= ast
.generics
.clone();
95 .push(syn
::GenericParam
::Lifetime(syn
::LifetimeDef
::new(
96 parse_quote
!('_derivative_strum
),
98 let (impl_generics2
, _
, _
) = generics
.split_for_impl();
99 let arms2
= arms
.clone();
100 let arms3
= arms
.clone();
101 match trait_variant
{
102 GenerateTraitVariant
::AsStaticStr
=> {
104 impl #impl_generics ::strum::AsStaticRef<str> for #name #ty_generics #where_clause {
105 fn as_static(&self) -> &'
static str {
113 GenerateTraitVariant
::From
=> {
115 impl #impl_generics ::std::convert::From<#name #ty_generics> for &'static str #where_clause {
116 fn from(x
: #name #ty_generics) -> &'static str {
122 impl #impl_generics2 ::std::convert::From<&'_derivative_strum #name #ty_generics> for &'static str #where_clause {
123 fn from(x
: &'_derivative_strum
#name #ty_generics) -> &'static str {