darling_core/codegen/
from_variant_impl.rs
1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use syn::Ident;
4
5use crate::codegen::{ExtractAttribute, ForwardAttrs, OuterFromImpl, TraitImpl};
6use crate::options::DataShape;
7use crate::util::PathList;
8
9pub struct FromVariantImpl<'a> {
10 pub base: TraitImpl<'a>,
11 pub ident: Option<&'a Ident>,
17 pub fields: Option<&'a Ident>,
22 pub discriminant: Option<&'a Ident>,
28 pub attr_names: &'a PathList,
29 pub forward_attrs: ForwardAttrs<'a>,
30 pub from_ident: bool,
31 pub supports: Option<&'a DataShape>,
32}
33
34impl<'a> ToTokens for FromVariantImpl<'a> {
35 fn to_tokens(&self, tokens: &mut TokenStream) {
36 let input = self.param_name();
37 let extractor = self.extractor();
38 let passed_ident = self
39 .ident
40 .as_ref()
41 .map(|i| quote!(#i: #input.ident.clone(),));
42 let passed_discriminant = self
43 .discriminant
44 .as_ref()
45 .map(|i| quote!(#i: #input.discriminant.as_ref().map(|(_, expr)| expr.clone()),));
46 let passed_attrs = self.forward_attrs.as_initializer();
47 let passed_fields = self
48 .fields
49 .as_ref()
50 .map(|i| quote!(#i: ::darling::ast::Fields::try_from(&#input.fields)?,));
51
52 let inits = self.base.initializers();
53 let post_transform = self.base.post_transform_call();
54
55 let default = if self.from_ident {
56 quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
57 } else {
58 self.base.fallback_decl()
59 };
60
61 let supports = self.supports.map(|i| {
62 quote! {
63 __errors.handle(#i.check(&#input.fields));
64 }
65 });
66
67 let error_declaration = self.base.declare_errors();
68 let require_fields = self.base.require_fields();
69 let error_check = self.base.check_errors();
70
71 self.wrap(
72 quote!(
73 fn from_variant(#input: &::darling::export::syn::Variant) -> ::darling::Result<Self> {
74 #error_declaration
75
76 #extractor
77
78 #supports
79
80 #require_fields
81
82 #error_check
83
84 #default
85
86 ::darling::export::Ok(Self {
87 #passed_ident
88 #passed_discriminant
89 #passed_attrs
90 #passed_fields
91 #inits
92 }) #post_transform
93 }
94 ),
95 tokens,
96 );
97 }
98}
99
100impl<'a> ExtractAttribute for FromVariantImpl<'a> {
101 fn local_declarations(&self) -> TokenStream {
102 self.base.local_declarations()
103 }
104
105 fn attr_names(&self) -> &PathList {
106 self.attr_names
107 }
108
109 fn forward_attrs(&self) -> &ForwardAttrs<'_> {
110 &self.forward_attrs
111 }
112
113 fn param_name(&self) -> TokenStream {
114 quote!(__variant)
115 }
116
117 fn core_loop(&self) -> TokenStream {
118 self.base.core_loop()
119 }
120}
121
122impl<'a> OuterFromImpl<'a> for FromVariantImpl<'a> {
123 fn trait_path(&self) -> syn::Path {
124 path!(::darling::FromVariant)
125 }
126
127 fn trait_bound(&self) -> syn::Path {
128 path!(::darling::FromMeta)
129 }
130
131 fn base(&'a self) -> &'a TraitImpl<'a> {
132 &self.base
133 }
134}