@@ -16,96 +16,85 @@ use syn::{Expr, GenericParam, Lit, LitStr, Type};
1616
1717use crate :: params:: Param ;
1818
19- /// One argument in the input to the parameterize macro
19+ /// The value of an [`Argument`]; everything after the equal sign
2020#[ derive( Clone , Debug ) ]
2121pub ( crate ) enum ArgumentValue {
2222 TypeList ( Vec < Type > ) ,
2323 LitList ( Vec < Lit > ) ,
2424 Str ( String ) ,
2525}
2626
27+ /// One argument in the input to the parameterize macro
2728#[ derive( Clone , Debug ) ]
2829pub ( crate ) struct Argument {
2930 pub ident : Ident ,
3031 pub value : ArgumentValue ,
3132}
3233
33- fn parse_typelist ( input : ParseStream ) -> Option < syn:: Result < Argument > > {
34- let ident = input. parse :: < Ident > ( ) . ok ( ) ?;
35- input. parse :: < syn:: token:: Eq > ( ) . ok ( ) ?;
36- if input. peek ( syn:: token:: Paren ) {
37- // everything after this point is an error instead of a no-match when it fails
38- let parse = || -> syn:: Result < Argument > {
39- let tt = input. parse :: < syn:: TypeTuple > ( ) ?;
40- let entries: Vec < Type > = tt. elems . iter ( ) . cloned ( ) . collect ( ) ;
41- Ok ( Argument {
42- ident,
43- value : ArgumentValue :: TypeList ( entries) ,
44- } )
45- } ;
46- Some ( parse ( ) )
47- } else {
48- None
49- }
34+ /// Parse a parenthesized list of types
35+ fn parse_typelist ( input : ParseStream ) -> Option < syn:: Result < ArgumentValue > > {
36+ let parse = || {
37+ let tt = input. parse :: < syn:: TypeTuple > ( ) ?;
38+ let entries: Vec < Type > = tt. elems . iter ( ) . cloned ( ) . collect ( ) ;
39+ Ok ( ArgumentValue :: TypeList ( entries) )
40+ } ;
41+
42+ // match on parentheses. Anything invalid after is an error
43+ input. peek ( syn:: token:: Paren ) . then_some ( parse ( ) )
5044}
5145
52- fn parse_litlist ( input : ParseStream ) -> Option < syn:: Result < Argument > > {
53- let ident = input. parse :: < Ident > ( ) . ok ( ) ?;
54- input. parse :: < syn:: token:: Eq > ( ) . ok ( ) ?;
55- if input. peek ( syn:: token:: Bracket ) {
56- // everything after this point is an error instead of a no-match when it fails
57- let parse = || -> syn:: Result < Argument > {
58- let exprs = input. parse :: < syn:: ExprArray > ( ) ?;
59- let entries: syn:: Result < Vec < Lit > > = exprs
60- . elems
61- . iter ( )
62- . map ( |expr : & Expr | -> syn:: Result < Lit > {
63- return if let Expr :: Lit ( lit) = expr {
64- Ok ( lit. lit . clone ( ) )
65- } else {
66- Err ( syn:: Error :: new ( expr. span ( ) , "Expression is not a literal" ) )
67- } ;
68- } )
69- . collect ( ) ;
70- Ok ( Argument {
71- ident,
72- value : ArgumentValue :: LitList ( entries?) ,
46+ /// Parse a bracketed list of literals
47+ fn parse_litlist ( input : ParseStream ) -> Option < syn:: Result < ArgumentValue > > {
48+ let parse = || {
49+ let exprs = input. parse :: < syn:: ExprArray > ( ) ?;
50+ let entries: syn:: Result < Vec < Lit > > = exprs
51+ . elems
52+ . iter ( )
53+ . map ( |expr : & Expr | -> syn:: Result < Lit > {
54+ return if let Expr :: Lit ( lit) = expr {
55+ Ok ( lit. lit . clone ( ) )
56+ } else {
57+ Err ( syn:: Error :: new ( expr. span ( ) , "Expression is not a literal" ) )
58+ } ;
7359 } )
74- } ;
60+ . collect ( ) ;
61+ Ok ( ArgumentValue :: LitList ( entries?) )
62+ } ;
7563
76- Some ( parse ( ) )
77- } else {
78- None
79- }
64+ // match on brackets. anything invalid after is an error
65+ input. peek ( syn:: token:: Bracket ) . then_some ( parse ( ) )
8066}
8167
82- fn parse_str ( input : ParseStream ) -> Option < syn:: Result < Argument > > {
83- let ident = input. parse :: < Ident > ( ) . ok ( ) ?;
84- input. parse :: < syn:: token:: Eq > ( ) . ok ( ) ?;
85-
86- // everything after this point is an error instead of a no-match when it fails
87-
88- let parse = || -> syn:: Result < Argument > {
89- let value = input. parse :: < LitStr > ( ) ?. value ( ) ;
90-
91- Ok ( Argument {
92- ident,
93- value : ArgumentValue :: Str ( value) ,
94- } )
95- } ;
96-
97- Some ( parse ( ) )
68+ /// Parse a string argument
69+ fn parse_str ( input : ParseStream ) -> Option < syn:: Result < ArgumentValue > > {
70+ // no way for a string argument parse to fail, it either matches or it doesnt
71+ input
72+ . parse :: < LitStr > ( )
73+ . ok ( )
74+ . map ( |lit| Ok ( ArgumentValue :: Str ( lit. value ( ) ) ) )
9875}
9976
10077impl Parse for Argument {
10178 fn parse ( input : ParseStream ) -> syn:: Result < Self > {
79+ // parse the ident and equals sign
80+ let ident = input. parse :: < Ident > ( ) ?;
81+ input. parse :: < syn:: token:: Eq > ( ) ?;
82+
83+ // iterate over the known parse functions for arguments
10284 [ parse_typelist, parse_litlist, parse_str]
10385 . iter ( )
10486 . find_map ( |f| {
87+ // fork the buffer, so we can rewind if there isnt a match
10588 let fork = input. fork ( ) ;
106- if let Some ( arg) = ( * f) ( & fork) {
89+
90+ // if the parse function returns a match, return a syn::Result<Argument>,
91+ // otherwise None to advance to the next parse function
92+ if let Some ( value) = ( * f) ( & fork) {
10793 input. advance_to ( & fork) ;
108- Some ( arg)
94+ Some ( value. map ( |v| Self {
95+ ident : ident. clone ( ) ,
96+ value : v,
97+ } ) )
10998 } else {
11099 None
111100 }
@@ -115,30 +104,14 @@ impl Parse for Argument {
115104}
116105
117106impl Argument {
118- pub fn short_name ( & self ) -> & str {
107+ /// Get a user-friendly name for the type of argument this is
108+ pub fn short_type ( & self ) -> & str {
119109 match self . value {
120110 ArgumentValue :: TypeList ( _) => "type list" ,
121111 ArgumentValue :: LitList ( _) => "const list" ,
122112 ArgumentValue :: Str ( _) => "string" ,
123113 }
124114 }
125- // pub fn match_paramlist(&self, gp: &GenericParam) -> Option<syn::Result<Vec<(Ident, Param)>>> {
126- // match (&self.ident, &self.value, gp) {
127- // (id, ArgumentValue::TypeList(tl), GenericParam::Type(tp)) if id == &tp.ident => Some(
128- // tl.iter()
129- // .map(|ty| (id.clone(), Param::Type(ty.clone())))
130- // .collect(),
131- // ),
132- //
133- // (id, ArgumentValue::LitList(ll), GenericParam::Const(cp)) if id == &cp.ident => Some(
134- // ll.iter()
135- // .map(|lit| (id.clone(), Param::Lit(lit.clone())))
136- // .collect(),
137- // ),
138- //
139- // _ => None,
140- // }
141- // }
142115}
143116
144117/// A list of arguments input to the macro
@@ -172,6 +145,9 @@ impl Extract for ArgumentList {
172145}
173146
174147impl ArgumentList {
148+ /// consume a paramlist from the argument list that matches the given generic parameter
149+ /// and return it.
150+ /// Returns an error if there is a type mismatch, or if there is not exactly one match
175151 pub fn consume_paramlist ( & mut self , gp : & GenericParam ) -> syn:: Result < Vec < ( Ident , Param ) > > {
176152 let ( g_ident, g_name) = match gp {
177153 GenericParam :: Lifetime ( lt) => Err ( syn:: Error :: new (
@@ -196,9 +172,9 @@ impl ArgumentList {
196172 ) ,
197173 ( ArgumentValue :: TypeList ( _) , _) | ( ArgumentValue :: LitList ( _) , _) => Some ( Err ( syn:: Error :: new (
198174 arg. ident . span ( ) ,
199- format ! ( "Mismatched parameterization: Expected {} list but found {}" , g_name, arg. short_name ( ) ) ,
175+ format ! ( "Mismatched parameterization: Expected {} list but found {}" , g_name, arg. short_type ( ) ) ,
200176 ) ) ) ,
201- /* fall through, in case theres a generic argument named for example "fmt". there probably shouldn't be though*/
177+ /* fall through, in case theres a generic argument named for example "fmt". there probably shouldn't be though */
202178 ( _, _) => None }
203179 } else {
204180 None
0 commit comments