1 use proc_macro2::TokenStream; 2 use quote::{quote, ToTokens}; 3 use syn::Ident; 4 5 use crate::{ 6 ast::Data, 7 codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}, 8 options::DeriveInputShapeSet, 9 util::PathList, 10 }; 11 12 use super::ForwardAttrs; 13 14 pub struct FromDeriveInputImpl<'a> { 15 pub ident: Option<&'a Ident>, 16 pub generics: Option<&'a Ident>, 17 pub vis: Option<&'a Ident>, 18 pub data: Option<&'a Ident>, 19 pub base: TraitImpl<'a>, 20 pub attr_names: &'a PathList, 21 pub forward_attrs: ForwardAttrs<'a>, 22 pub from_ident: bool, 23 pub supports: Option<&'a DeriveInputShapeSet>, 24 } 25 26 impl<'a> ToTokens for FromDeriveInputImpl<'a> { to_tokens(&self, tokens: &mut TokenStream)27 fn to_tokens(&self, tokens: &mut TokenStream) { 28 let ty_ident = self.base.ident; 29 let input = self.param_name(); 30 let post_transform = self.base.post_transform_call(); 31 32 if let Data::Struct(ref data) = self.base.data { 33 if data.is_newtype() { 34 self.wrap( 35 quote!{ 36 fn from_derive_input(#input: &::darling::export::syn::DeriveInput) -> ::darling::Result<Self> { 37 ::darling::export::Ok( 38 #ty_ident(::darling::FromDeriveInput::from_derive_input(#input)?) 39 ) #post_transform 40 } 41 }, 42 tokens, 43 ); 44 45 return; 46 } 47 } 48 49 let passed_ident = self 50 .ident 51 .as_ref() 52 .map(|i| quote!(#i: #input.ident.clone(),)); 53 let passed_vis = self.vis.as_ref().map(|i| quote!(#i: #input.vis.clone(),)); 54 let passed_generics = self 55 .generics 56 .as_ref() 57 .map(|i| quote!(#i: ::darling::FromGenerics::from_generics(&#input.generics)?,)); 58 let passed_attrs = self.forward_attrs.as_initializer(); 59 let passed_body = self 60 .data 61 .as_ref() 62 .map(|i| quote!(#i: ::darling::ast::Data::try_from(&#input.data)?,)); 63 64 let supports = self.supports.map(|i| { 65 quote! { 66 #i 67 __errors.handle(__validate_body(&#input.data)); 68 } 69 }); 70 71 let inits = self.base.initializers(); 72 let default = if self.from_ident { 73 quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());) 74 } else { 75 self.base.fallback_decl() 76 }; 77 78 let grab_attrs = self.extractor(); 79 80 let declare_errors = self.base.declare_errors(); 81 let require_fields = self.base.require_fields(); 82 let check_errors = self.base.check_errors(); 83 84 self.wrap( 85 quote! { 86 fn from_derive_input(#input: &::darling::export::syn::DeriveInput) -> ::darling::Result<Self> { 87 #declare_errors 88 89 #grab_attrs 90 91 #supports 92 93 #require_fields 94 95 #check_errors 96 97 #default 98 99 ::darling::export::Ok(#ty_ident { 100 #passed_ident 101 #passed_generics 102 #passed_vis 103 #passed_attrs 104 #passed_body 105 #inits 106 }) #post_transform 107 } 108 }, 109 tokens, 110 ); 111 } 112 } 113 114 impl<'a> ExtractAttribute for FromDeriveInputImpl<'a> { attr_names(&self) -> &PathList115 fn attr_names(&self) -> &PathList { 116 self.attr_names 117 } 118 forward_attrs(&self) -> &ForwardAttrs<'_>119 fn forward_attrs(&self) -> &ForwardAttrs<'_> { 120 &self.forward_attrs 121 } 122 param_name(&self) -> TokenStream123 fn param_name(&self) -> TokenStream { 124 quote!(__di) 125 } 126 core_loop(&self) -> TokenStream127 fn core_loop(&self) -> TokenStream { 128 self.base.core_loop() 129 } 130 local_declarations(&self) -> TokenStream131 fn local_declarations(&self) -> TokenStream { 132 self.base.local_declarations() 133 } 134 } 135 136 impl<'a> OuterFromImpl<'a> for FromDeriveInputImpl<'a> { trait_path(&self) -> syn::Path137 fn trait_path(&self) -> syn::Path { 138 path!(::darling::FromDeriveInput) 139 } 140 trait_bound(&self) -> syn::Path141 fn trait_bound(&self) -> syn::Path { 142 path!(::darling::FromMeta) 143 } 144 base(&'a self) -> &'a TraitImpl<'a>145 fn base(&'a self) -> &'a TraitImpl<'a> { 146 &self.base 147 } 148 } 149