@@ -10,10 +10,10 @@ use syn::visit_mut::VisitMut;
1010struct AsyncStreamImpl {
1111 yielder : syn:: Ident ,
1212 stmts : Vec < syn:: Stmt > ,
13- num_yield : u32 ,
1413}
1514
1615struct Scrub {
16+ is_try : bool ,
1717 yielder : syn:: Ident ,
1818 unit : Box < syn:: Expr > ,
1919 num_yield : u32 ,
@@ -25,42 +25,51 @@ impl Parse for AsyncStreamImpl {
2525 input. parse :: < Token ! [ , ] > ( ) ?;
2626
2727 let mut stmts = vec ! [ ] ;
28- let mut scrub = Scrub {
29- yielder,
30- unit : syn:: parse_quote!( ( ) ) ,
31- num_yield : 0 ,
32- } ;
3328
3429 while !input. is_empty ( ) {
35- let mut stmt = input. parse ( ) ?;
36- scrub. visit_stmt_mut ( & mut stmt) ;
37- stmts. push ( stmt) ;
30+ stmts. push ( input. parse ( ) ?) ;
3831 }
3932
40- let Scrub { yielder, num_yield, .. } = scrub;
41-
4233 Ok ( AsyncStreamImpl {
4334 yielder,
4435 stmts,
45- num_yield,
4636 } )
4737 }
4838}
4939
5040impl VisitMut for Scrub {
5141 fn visit_expr_mut ( & mut self , i : & mut syn:: Expr ) {
5242 match i {
53- syn:: Expr :: Yield ( expr ) => {
43+ syn:: Expr :: Yield ( yield_expr ) => {
5444 self . num_yield += 1 ;
5545
56- let value_expr = if let Some ( ref e) = expr . expr {
46+ let value_expr = if let Some ( ref e) = yield_expr . expr {
5747 e
5848 } else {
5949 & self . unit
6050 } ;
6151
6252 let ident = & self . yielder ;
63- * i = syn:: parse_quote! { #ident. send( #value_expr) . await } ;
53+
54+ * i = if self . is_try {
55+ syn:: parse_quote! { #ident. send( Ok ( #value_expr) ) . await }
56+ } else {
57+ syn:: parse_quote! { #ident. send( #value_expr) . await }
58+ } ;
59+ }
60+ syn:: Expr :: Try ( try_expr) => {
61+ let ident = & self . yielder ;
62+ let e = & try_expr. expr ;
63+
64+ * i = syn:: parse_quote! {
65+ match #e {
66+ Ok ( v) => v,
67+ Err ( e) => {
68+ #ident. send( Err ( e) ) . await ;
69+ return ;
70+ }
71+ }
72+ } ;
6473 }
6574 expr => syn:: visit_mut:: visit_expr_mut ( self , expr) ,
6675 }
@@ -71,11 +80,58 @@ impl VisitMut for Scrub {
7180pub fn async_stream_impl ( input : TokenStream ) -> TokenStream {
7281 let AsyncStreamImpl {
7382 yielder,
74- stmts,
75- num_yield,
83+ mut stmts,
7684 } = syn:: parse_macro_input!( input as AsyncStreamImpl ) ;
7785
78- if num_yield == 0 {
86+ let mut scrub = Scrub {
87+ is_try : false ,
88+ yielder,
89+ unit : syn:: parse_quote!( ( ) ) ,
90+ num_yield : 0 ,
91+ } ;
92+
93+ for mut stmt in & mut stmts {
94+ scrub. visit_stmt_mut ( & mut stmt) ;
95+ }
96+
97+ if scrub. num_yield == 0 {
98+ let yielder = & scrub. yielder ;
99+
100+ quote ! ( {
101+ if false {
102+ #yielder. send( ( ) ) . await ;
103+ }
104+
105+ #( #stmts) *
106+ } ) . into ( )
107+ } else {
108+ quote ! ( {
109+ #( #stmts) *
110+ } ) . into ( )
111+ }
112+ }
113+
114+ #[ proc_macro_hack]
115+ pub fn async_try_stream_impl ( input : TokenStream ) -> TokenStream {
116+ let AsyncStreamImpl {
117+ yielder,
118+ mut stmts,
119+ } = syn:: parse_macro_input!( input as AsyncStreamImpl ) ;
120+
121+ let mut scrub = Scrub {
122+ is_try : true ,
123+ yielder,
124+ unit : syn:: parse_quote!( ( ) ) ,
125+ num_yield : 0 ,
126+ } ;
127+
128+ for mut stmt in & mut stmts {
129+ scrub. visit_stmt_mut ( & mut stmt) ;
130+ }
131+
132+ if scrub. num_yield == 0 {
133+ let yielder = & scrub. yielder ;
134+
79135 quote ! ( {
80136 if false {
81137 #yielder. send( ( ) ) . await ;
0 commit comments