• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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