@@ -22,30 +22,74 @@ impl Parse for AsyncItem {
2222
2323pub struct RecursionArgs {
2424 pub send_bound : bool ,
25- }
26-
27- impl Default for RecursionArgs {
28- fn default ( ) -> Self {
29- RecursionArgs { send_bound : true }
30- }
25+ pub sync_bound : bool ,
3126}
3227
3328/// Custom keywords for parser
3429mod kw {
3530 syn:: custom_keyword!( Send ) ;
31+ syn:: custom_keyword!( Sync ) ;
3632}
3733
38- impl Parse for RecursionArgs {
34+ #[ derive( Debug , PartialEq , Eq ) ]
35+ enum Arg {
36+ NotSend ,
37+ Sync ,
38+ }
39+
40+ impl std:: fmt:: Display for Arg {
41+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
42+ match self {
43+ Self :: NotSend => write ! ( f, "?Send" ) ,
44+ Self :: Sync => write ! ( f, "Sync" ) ,
45+ }
46+ }
47+ }
48+
49+ impl Parse for Arg {
3950 fn parse ( input : ParseStream ) -> Result < Self > {
40- // Check for the `?Send` option
4151 if input. peek ( Token ! [ ?] ) {
4252 input. parse :: < Question > ( ) ?;
4353 input. parse :: < kw:: Send > ( ) ?;
44- Ok ( Self { send_bound : false } )
45- } else if !input. is_empty ( ) {
46- Err ( input. error ( "expected `?Send` or empty" ) )
54+ Ok ( Arg :: NotSend )
4755 } else {
48- Ok ( Self :: default ( ) )
56+ input. parse :: < kw:: Sync > ( ) ?;
57+ Ok ( Arg :: Sync )
4958 }
5059 }
5160}
61+
62+ impl Parse for RecursionArgs {
63+ fn parse ( input : ParseStream ) -> Result < Self > {
64+ let mut send_bound: bool = true ;
65+ let mut sync_bound: bool = false ;
66+
67+ let args_parsed: Vec < Arg > =
68+ syn:: punctuated:: Punctuated :: < Arg , syn:: Token ![ , ] > :: parse_terminated ( input)
69+ . map_err ( |e| input. error ( format ! ( "failed to parse macro arguments: {e}" ) ) ) ?
70+ . into_iter ( )
71+ . collect ( ) ;
72+
73+ // Avoid sloppy input
74+ if args_parsed. len ( ) > 2 {
75+ return Err ( Error :: new ( Span :: call_site ( ) , "received too many arguments" ) ) ;
76+ } else if args_parsed. len ( ) == 2 && args_parsed[ 0 ] == args_parsed[ 1 ] {
77+ return Err ( Error :: new (
78+ Span :: call_site ( ) ,
79+ format ! ( "received duplicate argument: `{}`" , args_parsed[ 0 ] ) ,
80+ ) ) ;
81+ }
82+
83+ for arg in args_parsed {
84+ match arg {
85+ Arg :: NotSend => send_bound = false ,
86+ Arg :: Sync => sync_bound = true ,
87+ }
88+ }
89+
90+ Ok ( Self {
91+ send_bound,
92+ sync_bound,
93+ } )
94+ }
95+ }
0 commit comments