@@ -14,18 +14,13 @@ pub struct ParsedAttributes {
1414    pub  passthrough_attrs :  Vec < Attribute > , 
1515} 
1616
17- // TODO: ATTR could this instead be used as Result<ParsedAttribute> to encapsulate error states 
18- pub  enum  ParsedAttribute < ' a >  { 
19-     /// A single attribute was found 
20-      Single ( & ' a  Attribute ) , 
21-     /// An attribute was not found, but this is ok 
22-      Absent , 
23-     /// An attribute was not found, and this is an error 
24-      AbsentRequired , 
25-     /// Multiple attributes were found, but this is ok 
26-      Multiple ( Vec < & ' a  Attribute > ) , 
27-     /// Multiple attributes were found, but this is an error 
28-      MultipleDisallowed ( Vec < & ' a  Attribute > ) , 
17+ pub  enum  AttributeConstraint  { 
18+     /// Indicates that there must be only one of this attribute 
19+      Unique , 
20+     /// Indicates there can be multiple of this attribute 
21+      Duplicate , 
22+     /// Indicates that this attribute is required 
23+      Required , 
2924} 
3025
3126/// Iterate the attributes of the method to extract cfg attributes 
@@ -48,32 +43,49 @@ pub fn extract_docs(attrs: &[Attribute]) -> Vec<Attribute> {
4843
4944impl < ' a >  ParsedAttributes  { 
5045    /// Collects a Map of all attributes found from the allowed list 
51-      /// Will error if an attribute which is not in the allowed list is found 
46+      /// Will error if an attribute which is not in the allowed list is found, or attribute is used incorrectly  
5247     pub  fn  require_attributes ( 
5348        mut  attrs :  Vec < Attribute > , 
54-         allowed :  & ' a  [ & str ] , 
49+         allowed :  & ' a  [ ( AttributeConstraint ,   & str ) ] , 
5550    )  -> Result < ParsedAttributes >  { 
5651        let  mut  output = BTreeMap :: < String ,  Vec < Attribute > > :: default ( ) ; 
5752        for  attr in  attrs. drain ( ..)  { 
58-             let  index = allowed
59-                 . iter ( ) 
60-                  . position ( |string|  path_compare_str ( attr . meta . path ( ) ,   & parser :: split_path ( string ) ) ) ; 
53+             let  index = allowed. iter ( ) . position ( | ( _ ,  string ) |  { 
54+                 path_compare_str ( attr . meta . path ( ) ,   & parser :: split_path ( string ) ) 
55+             } ) ; 
6156            if  let  Some ( index)  = index { 
62-                 // TODO: ATTR Doesn't error on duplicates / distinguish allowed and disallowed duplicates 
63-                 match  output. entry ( allowed[ index] . into ( ) )  { 
64-                     Entry :: Occupied ( mut  entry)  => { 
65-                         entry. get_mut ( ) . push ( attr) ; 
66-                     } 
67-                     Entry :: Vacant ( entry)  => { 
68-                         entry. insert ( vec ! [ attr] ) ; 
57+                 match  allowed[ index] . 0  { 
58+                     AttributeConstraint :: Unique  => { 
59+                         match  output. entry ( allowed[ index] . 1 . into ( ) )  { 
60+                             Entry :: Occupied ( _)  => return  Err ( Error :: new_spanned ( 
61+                                 attr, 
62+                                 "There must be at most one of this attribute on this given item" , 
63+                             ) ) , 
64+                             Entry :: Vacant ( entry)  => { 
65+                                 entry. insert ( vec ! [ attr] ) ; 
66+                             } 
67+                         } 
6968                    } 
69+                     AttributeConstraint :: Duplicate  => match  output. entry ( allowed[ index] . 1 . into ( ) )  { 
70+                         Entry :: Occupied ( mut  entry)  => { 
71+                             entry. get_mut ( ) . push ( attr) ; 
72+                         } 
73+                         Entry :: Vacant ( entry)  => { 
74+                             entry. insert ( vec ! [ attr] ) ; 
75+                         } 
76+                     } , 
77+                     AttributeConstraint :: Required  => { } 
7078                } 
7179            }  else  { 
7280                return  Err ( Error :: new ( 
7381                    attr. span ( ) , 
7482                    format ! ( 
7583                        "Unsupported attribute! The only attributes allowed on this item are\n {}" , 
76-                         allowed. join( ", " ) 
84+                         allowed
85+                             . iter( ) 
86+                             . map( |( _,  string) | * string) 
87+                             . collect:: <Vec <_>>( ) 
88+                             . join( ", " ) 
7789                    ) , 
7890                ) ) ; 
7991            } 
@@ -122,18 +134,6 @@ impl<'a> ParsedAttributes {
122134        self . cxx_qt_attrs . get ( key) ?. first ( ) 
123135    } 
124136
125-     pub  fn  require_one ( & self ,  key :  & str )  -> ParsedAttribute  { 
126-         if  let  Some ( attrs)  = self . cxx_qt_attrs . get ( key)  { 
127-             if  attrs. len ( )  != 1  { 
128-                 ParsedAttribute :: MultipleDisallowed ( attrs. iter ( ) . by_ref ( ) . collect ( ) ) 
129-             }  else  { 
130-                 ParsedAttribute :: Single ( attrs. first ( ) . expect ( "Expected at least one attribute" ) ) 
131-             } 
132-         }  else  { 
133-             ParsedAttribute :: Absent 
134-         } 
135-     } 
136- 
137137    /// Check if CXX-Qt or passthrough attributes contains a particular key 
138138     pub  fn  contains_key ( & self ,  key :  & str )  -> bool  { 
139139        self . cxx_qt_attrs . contains_key ( key)  // TODO: Check in passthrough too 
0 commit comments