1 use quote::ToTokens; 2 3 use crate::{ast::Data, codegen::FromAttributesImpl, Error, Result}; 4 5 use super::{OuterFrom, ParseAttribute, ParseData}; 6 7 /// Receiver for derived `FromAttributes` impls. 8 pub struct FromAttributesOptions { 9 // Note: FromAttributes has no behaviors beyond those common 10 // to all the `OuterFrom` traits. 11 pub base: OuterFrom, 12 } 13 14 impl FromAttributesOptions { new(di: &syn::DeriveInput) -> Result<Self>15 pub fn new(di: &syn::DeriveInput) -> Result<Self> { 16 let opts = (Self { 17 base: OuterFrom::start(di)?, 18 }) 19 .parse_attributes(&di.attrs)? 20 .parse_body(&di.data)?; 21 22 if !opts.is_newtype() && opts.base.attr_names.is_empty() { 23 Err(Error::custom( 24 "FromAttributes without attributes collects nothing", 25 )) 26 } else { 27 Ok(opts) 28 } 29 } 30 is_newtype(&self) -> bool31 fn is_newtype(&self) -> bool { 32 if let Data::Struct(ref data) = self.base.container.data { 33 data.is_newtype() 34 } else { 35 false 36 } 37 } 38 } 39 40 impl ParseAttribute for FromAttributesOptions { parse_nested(&mut self, mi: &syn::Meta) -> Result<()>41 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { 42 self.base.parse_nested(mi) 43 } 44 } 45 46 impl ParseData for FromAttributesOptions { parse_variant(&mut self, variant: &syn::Variant) -> Result<()>47 fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> { 48 self.base.parse_variant(variant) 49 } 50 parse_field(&mut self, field: &syn::Field) -> Result<()>51 fn parse_field(&mut self, field: &syn::Field) -> Result<()> { 52 self.base.parse_field(field) 53 } 54 validate_body(&self, errors: &mut crate::error::Accumulator)55 fn validate_body(&self, errors: &mut crate::error::Accumulator) { 56 self.base.validate_body(errors); 57 } 58 } 59 60 impl<'a> From<&'a FromAttributesOptions> for FromAttributesImpl<'a> { from(v: &'a FromAttributesOptions) -> Self61 fn from(v: &'a FromAttributesOptions) -> Self { 62 FromAttributesImpl { 63 base: (&v.base.container).into(), 64 attr_names: &v.base.attr_names, 65 forward_attrs: v.base.as_forward_attrs(), 66 } 67 } 68 } 69 70 impl ToTokens for FromAttributesOptions { to_tokens(&self, tokens: &mut proc_macro2::TokenStream)71 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { 72 FromAttributesImpl::from(self).to_tokens(tokens) 73 } 74 } 75