1+ use  hyper:: body:: Buf ; 
2+ use  std:: sync:: atomic:: { AtomicBool ,  Ordering } ; 
3+ use  std:: sync:: Arc ; 
4+ use  tokio:: sync:: Notify ; 
5+ 
6+ #[ derive( Clone ) ]  
7+ pub  struct  EosSignaler  { 
8+     notifier :  Arc < Notify > , 
9+ } 
10+ 
11+ impl  EosSignaler  { 
12+     fn  notify_eos ( & self )  { 
13+         self . notifier . notify_waiters ( ) ; 
14+     } 
15+ 
16+     pub  async  fn  wait_till_eos ( self )  { 
17+         self . notifier . notified ( ) . await ; 
18+     } 
19+ } 
20+ 
21+ pub  struct  AlertOnEos < B >  { 
22+     inner :  B , 
23+     signaler :  EosSignaler , 
24+     // I'd rather we consumed the signaler, but it would require something like AtomicOption, 
25+     // arc_swap::ArcSwapOption was tried, but it only returns an Arc, and the value cannot be consumed (swapped). 
26+     // One could write an AtomicOption type (like this https://docs.rs/atomic-option/0.1.2/atomic_option/), 
27+     // but it requires both unsafe and additional heap allocation, which is not worth it. 
28+     has_already_signaled :  AtomicBool , 
29+ } 
30+ 
31+ impl < B >  AlertOnEos < B >  { 
32+     pub  fn  new ( inner :  B )  -> ( Self ,  EosSignaler )  { 
33+         let  signal = EosSignaler  { 
34+             notifier :  Arc :: new ( Notify :: new ( ) ) , 
35+         } ; 
36+         let  this = Self  { 
37+             inner, 
38+             signaler :  signal. clone ( ) , 
39+             has_already_signaled :  AtomicBool :: new ( false ) , 
40+         } ; 
41+         ( this,  signal) 
42+     } 
43+ } 
44+ 
45+ impl < B :  Buf >  Buf  for  AlertOnEos < B >  { 
46+     fn  remaining ( & self )  -> usize  { 
47+         self . inner . remaining ( ) 
48+     } 
49+ 
50+     fn  chunk ( & self )  -> & [ u8 ]  { 
51+         self . inner . chunk ( ) 
52+     } 
53+ 
54+     fn  advance ( & mut  self ,  cnt :  usize )  { 
55+         self . inner . advance ( cnt) ; 
56+         if  !self . inner . has_remaining ( )  && !self . has_already_signaled . swap ( true ,  Ordering :: AcqRel )  { 
57+             self . signaler . notify_eos ( ) ; 
58+         } 
59+     } 
60+ } 
61+ 
62+ #[ cfg( test) ]  
63+ mod  tests { 
64+ 
65+ } 
0 commit comments