1 use crate::helpers::{non_enum_error, snakify, HasStrumVariantProperties};
2 use proc_macro2::TokenStream;
3 use quote::{format_ident, quote, ToTokens};
4 use syn::{Data, DeriveInput};
5
enum_try_as_inner(ast: &DeriveInput) -> syn::Result<TokenStream>6 pub fn enum_try_as_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
7 let variants = match &ast.data {
8 Data::Enum(v) => &v.variants,
9 _ => return Err(non_enum_error()),
10 };
11
12 let enum_name = &ast.ident;
13
14 let variants: Vec<_> = variants
15 .iter()
16 .filter_map(|variant| {
17 if variant.get_variant_properties().ok()?.disabled.is_some() {
18 return None;
19 }
20
21 match &variant.fields {
22 syn::Fields::Unnamed(values) => {
23 let variant_name = &variant.ident;
24 let types: Vec<_> = values.unnamed.iter().map(|field| {
25 field.to_token_stream()
26 }).collect();
27 let field_names: Vec<_> = values.unnamed.iter().enumerate().map(|(i, _)| {
28 let name = "x".repeat(i + 1);
29 let name = format_ident!("{}", name);
30 quote! {#name}
31 }).collect();
32
33 let move_fn_name = format_ident!("try_as_{}", snakify(&variant_name.to_string()));
34 let ref_fn_name = format_ident!("try_as_{}_ref", snakify(&variant_name.to_string()));
35 let mut_fn_name = format_ident!("try_as_{}_mut", snakify(&variant_name.to_string()));
36
37 Some(quote! {
38 #[must_use]
39 #[inline]
40 pub fn #move_fn_name(self) -> ::core::option::Option<(#(#types),*)> {
41 match self {
42 #enum_name::#variant_name (#(#field_names),*) => Some((#(#field_names),*)),
43 _ => None
44 }
45 }
46
47 #[must_use]
48 #[inline]
49 pub const fn #ref_fn_name(&self) -> ::core::option::Option<(#(&#types),*)> {
50 match self {
51 #enum_name::#variant_name (#(#field_names),*) => Some((#(#field_names),*)),
52 _ => None
53 }
54 }
55
56 #[must_use]
57 #[inline]
58 pub fn #mut_fn_name(&mut self) -> ::core::option::Option<(#(&mut #types),*)> {
59 match self {
60 #enum_name::#variant_name (#(#field_names),*) => Some((#(#field_names),*)),
61 _ => None
62 }
63 }
64 })
65 },
66 _ => {
67 return None;
68 }
69 }
70
71 })
72 .collect();
73
74 Ok(quote! {
75 impl #enum_name {
76 #(#variants)*
77 }
78 }
79 .into())
80 }
81