1 use proc_macro2::Ident; 2 use syn::Path; 3 4 use crate::ast::NestedMeta; 5 use crate::util::PathList; 6 use crate::{Error, FromField, FromMeta, Result}; 7 8 use super::ParseAttribute; 9 10 /// The `attrs` magic field and attributes that influence its behavior. 11 #[derive(Debug, Clone)] 12 pub struct AttrsField { 13 /// The ident of the field that will receive the forwarded attributes. 14 pub ident: Ident, 15 /// Path of the function that will be called to convert the `Vec` of 16 /// forwarded attributes into the type expected by the field in `ident`. 17 pub with: Option<Path>, 18 } 19 20 impl FromField for AttrsField { from_field(field: &syn::Field) -> crate::Result<Self>21 fn from_field(field: &syn::Field) -> crate::Result<Self> { 22 let result = Self { 23 ident: field.ident.clone().ok_or_else(|| { 24 Error::custom("attributes receiver must be named field").with_span(field) 25 })?, 26 with: None, 27 }; 28 29 result.parse_attributes(&field.attrs) 30 } 31 } 32 33 impl ParseAttribute for AttrsField { parse_nested(&mut self, mi: &syn::Meta) -> crate::Result<()>34 fn parse_nested(&mut self, mi: &syn::Meta) -> crate::Result<()> { 35 if mi.path().is_ident("with") { 36 if self.with.is_some() { 37 return Err(Error::duplicate_field_path(mi.path()).with_span(mi)); 38 } 39 40 self.with = FromMeta::from_meta(mi)?; 41 Ok(()) 42 } else { 43 Err(Error::unknown_field_path_with_alts(mi.path(), &["with"]).with_span(mi)) 44 } 45 } 46 } 47 48 /// A rule about which attributes to forward to the generated struct. 49 #[derive(Debug, Clone, PartialEq, Eq)] 50 pub enum ForwardAttrsFilter { 51 All, 52 Only(PathList), 53 } 54 55 impl ForwardAttrsFilter { 56 /// Returns `true` if this will not forward any attributes. is_empty(&self) -> bool57 pub fn is_empty(&self) -> bool { 58 match *self { 59 ForwardAttrsFilter::All => false, 60 ForwardAttrsFilter::Only(ref list) => list.is_empty(), 61 } 62 } 63 } 64 65 impl FromMeta for ForwardAttrsFilter { from_word() -> Result<Self>66 fn from_word() -> Result<Self> { 67 Ok(ForwardAttrsFilter::All) 68 } 69 from_list(nested: &[NestedMeta]) -> Result<Self>70 fn from_list(nested: &[NestedMeta]) -> Result<Self> { 71 Ok(ForwardAttrsFilter::Only(PathList::from_list(nested)?)) 72 } 73 } 74