1 use proc_macro2::TokenStream; 2 use quote::ToTokens; 3 use syn::Ident; 4 5 use crate::codegen::FromDeriveInputImpl; 6 use crate::options::{DeriveInputShapeSet, OuterFrom, ParseAttribute, ParseData}; 7 use crate::{FromMeta, Result}; 8 9 #[derive(Debug)] 10 pub struct FdiOptions { 11 pub base: OuterFrom, 12 13 /// The field on the target struct which should receive the type visibility, if any. 14 pub vis: Option<Ident>, 15 16 /// The field on the target struct which should receive the type generics, if any. 17 pub generics: Option<Ident>, 18 19 pub data: Option<Ident>, 20 21 pub supports: Option<DeriveInputShapeSet>, 22 } 23 24 impl FdiOptions { new(di: &syn::DeriveInput) -> Result<Self>25 pub fn new(di: &syn::DeriveInput) -> Result<Self> { 26 (FdiOptions { 27 base: OuterFrom::start(di)?, 28 vis: Default::default(), 29 generics: Default::default(), 30 data: Default::default(), 31 supports: Default::default(), 32 }) 33 .parse_attributes(&di.attrs)? 34 .parse_body(&di.data) 35 } 36 } 37 38 impl ParseAttribute for FdiOptions { parse_nested(&mut self, mi: &syn::Meta) -> Result<()>39 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { 40 if mi.path().is_ident("supports") { 41 self.supports = FromMeta::from_meta(mi)?; 42 Ok(()) 43 } else { 44 self.base.parse_nested(mi) 45 } 46 } 47 } 48 49 impl ParseData for FdiOptions { parse_variant(&mut self, variant: &syn::Variant) -> Result<()>50 fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> { 51 self.base.parse_variant(variant) 52 } 53 parse_field(&mut self, field: &syn::Field) -> Result<()>54 fn parse_field(&mut self, field: &syn::Field) -> Result<()> { 55 match field.ident.as_ref().map(|v| v.to_string()).as_deref() { 56 Some("vis") => { 57 self.vis.clone_from(&field.ident); 58 Ok(()) 59 } 60 Some("data") => { 61 self.data.clone_from(&field.ident); 62 Ok(()) 63 } 64 Some("generics") => { 65 self.generics.clone_from(&field.ident); 66 Ok(()) 67 } 68 _ => self.base.parse_field(field), 69 } 70 } 71 validate_body(&self, errors: &mut crate::error::Accumulator)72 fn validate_body(&self, errors: &mut crate::error::Accumulator) { 73 self.base.validate_body(errors); 74 } 75 } 76 77 impl<'a> From<&'a FdiOptions> for FromDeriveInputImpl<'a> { from(v: &'a FdiOptions) -> Self78 fn from(v: &'a FdiOptions) -> Self { 79 FromDeriveInputImpl { 80 base: (&v.base.container).into(), 81 attr_names: &v.base.attr_names, 82 from_ident: v.base.from_ident, 83 ident: v.base.ident.as_ref(), 84 vis: v.vis.as_ref(), 85 data: v.data.as_ref(), 86 generics: v.generics.as_ref(), 87 forward_attrs: v.base.as_forward_attrs(), 88 supports: v.supports.as_ref(), 89 } 90 } 91 } 92 93 impl ToTokens for FdiOptions { to_tokens(&self, tokens: &mut TokenStream)94 fn to_tokens(&self, tokens: &mut TokenStream) { 95 FromDeriveInputImpl::from(self).to_tokens(tokens) 96 } 97 } 98