1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use proc_macro2::TokenStream; use quote::ToTokens; use syn::{self, Ident}; use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}; use options::{DataShape, ForwardAttrs}; use util::PathList; pub struct FromVariantImpl<'a> { pub base: TraitImpl<'a>, pub ident: Option<&'a Ident>, pub fields: Option<&'a Ident>, pub attrs: Option<&'a Ident>, pub attr_names: &'a PathList, pub forward_attrs: Option<&'a ForwardAttrs>, pub from_ident: bool, pub supports: Option<&'a DataShape>, } impl<'a> ToTokens for FromVariantImpl<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let input = self.param_name(); let extractor = self.extractor(); let passed_ident = self.ident .as_ref() .map(|i| quote!(#i: #input.ident.clone(),)); let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,)); let passed_fields = self.fields .as_ref() .map(|i| quote!(#i: ::darling::ast::Fields::try_from(&#input.fields)?,)); let inits = self.base.initializers(); let map = self.base.map_fn(); let default = if self.from_ident { quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());) } else { self.base.fallback_decl() }; let supports = self.supports.map(|i| { quote! { #i __validate_data(&#input.fields)?; } }); let error_declaration = self.base.declare_errors(); let require_fields = self.base.require_fields(); let error_check = self.base.check_errors(); self.wrap( quote!( fn from_variant(#input: &::syn::Variant) -> ::darling::Result<Self> { #error_declaration #extractor #supports #require_fields #error_check #default ::darling::export::Ok(Self { #passed_ident #passed_attrs #passed_fields #inits }) #map } ), tokens, ); } } impl<'a> ExtractAttribute for FromVariantImpl<'a> { fn local_declarations(&self) -> TokenStream { self.base.local_declarations() } fn immutable_declarations(&self) -> TokenStream { self.base.immutable_declarations() } fn attr_names(&self) -> &PathList { &self.attr_names } fn forwarded_attrs(&self) -> Option<&ForwardAttrs> { self.forward_attrs } fn param_name(&self) -> TokenStream { quote!(__variant) } fn core_loop(&self) -> TokenStream { self.base.core_loop() } } impl<'a> OuterFromImpl<'a> for FromVariantImpl<'a> { fn trait_path(&self) -> syn::Path { path!(::darling::FromVariant) } fn trait_bound(&self) -> syn::Path { path!(::darling::FromMeta) } fn base(&'a self) -> &'a TraitImpl<'a> { &self.base } }