1 use proc_macro2
::TokenStream
;
3 use syn
::{Data, DeriveInput, Fields, LitStr}
;
5 use crate::helpers
::{non_enum_error, HasStrumVariantProperties, HasTypeProperties}
;
7 pub fn enum_message_inner(ast
: &DeriveInput
) -> syn
::Result
<TokenStream
> {
9 let (impl_generics
, ty_generics
, where_clause
) = ast
.generics
.split_for_impl();
10 let variants
= match &ast
.data
{
11 Data
::Enum(v
) => &v
.variants
,
12 _
=> return Err(non_enum_error()),
15 let type_properties
= ast
.get_type_properties()?
;
16 let strum_module_path
= type_properties
.crate_module_path();
18 let mut arms
= Vec
::new();
19 let mut detailed_arms
= Vec
::new();
20 let mut documentation_arms
= Vec
::new();
21 let mut serializations
= Vec
::new();
23 for variant
in variants
{
24 let variant_properties
= variant
.get_variant_properties()?
;
25 let messages
= variant_properties
.message
.as_ref();
26 let detailed_messages
= variant_properties
.detailed_message
.as_ref();
27 let documentation
= &variant_properties
.documentation
;
28 let ident
= &variant
.ident
;
30 let params
= match variant
.fields
{
31 Fields
::Unit
=> quote
! {}
,
32 Fields
::Unnamed(..) => quote
! { (..) }
,
33 Fields
::Named(..) => quote
! { {..}
},
36 // You can't disable getting the serializations.
38 let serialization_variants
=
39 variant_properties
.get_serializations(type_properties
.case_style
);
41 let count
= serialization_variants
.len();
42 serializations
.push(quote
! {
43 &#name::#ident #params => {
44 static ARR
: [&'
static str; #count] = [#(#serialization_variants),*];
50 // But you can disable the messages.
51 if variant_properties
.disabled
.is_some() {
55 if let Some(msg
) = messages
{
56 let params
= params
.clone();
58 // Push the simple message.
59 let tokens
= quote
! { &#name::#ident #params => ::core::option::Option::Some(#msg) }
;
60 arms
.push(tokens
.clone());
62 if detailed_messages
.is_none() {
63 detailed_arms
.push(tokens
);
67 if let Some(msg
) = detailed_messages
{
68 let params
= params
.clone();
69 // Push the detailed message.
71 .push(quote
! { &#name::#ident #params => ::core::option::Option::Some(#msg) }
);
74 if !documentation
.is_empty() {
75 let params
= params
.clone();
76 // Strip a single leading space from each documentation line.
77 let documentation
: Vec
<LitStr
> = documentation
.iter().map(|lit_str
| {
78 let line
= lit_str
.value();
79 if line
.starts_with(' '
) {
80 LitStr
::new(&line
.as_str()[1..], lit_str
.span())
85 if documentation
.len() == 1 {
86 let text
= &documentation
[0];
88 .push(quote
! { &#name::#ident #params => ::core::option::Option::Some(#text) }
);
90 // Push the documentation.
93 &#name::#ident #params => ::core::option::Option::Some(concat!(#(concat!(#documentation, "\n")),*))
99 if arms
.len() < variants
.len() {
100 arms
.push(quote
! { _ => ::core::option::Option::None }
);
103 if detailed_arms
.len() < variants
.len() {
104 detailed_arms
.push(quote
! { _ => ::core::option::Option::None }
);
107 if documentation_arms
.len() < variants
.len() {
108 documentation_arms
.push(quote
! { _ => ::core::option::Option::None }
);
112 impl #impl_generics #strum_module_path::EnumMessage for #name #ty_generics #where_clause {
113 fn get_message(&self) -> ::core
::option
::Option
<&'
static str> {
119 fn get_detailed_message(&self) -> ::core
::option
::Option
<&'
static str> {
125 fn get_documentation(&self) -> ::core
::option
::Option
<&'
static str> {
127 #(#documentation_arms),*
131 fn get_serializations(&self) -> &'
static [&'
static str] {