1- use anyhow:: { Result , bail} ;
2- use std:: collections:: HashSet ;
31use std:: fmt;
2+ use std:: { collections:: HashSet , fmt:: Write } ;
43use wit_parser:: { Function , FunctionKind , Resolve , WorldKey } ;
54
5+ use crate :: filter:: { FilterMode , FilterRule , FilterSet , FilterTarget } ;
6+
67/// Structure used to parse the command line argument `--async` consistently
78/// across guest generators.
89#[ cfg_attr( feature = "clap" , derive( clap:: Parser ) ) ]
@@ -33,9 +34,9 @@ pub struct AsyncFilterSet {
3334 arg(
3435 long = "async" ,
3536 value_parser = parse_async,
36- value_delimiter =',' ,
37+ value_delimiter = ',' ,
3738 value_name = "FILTER" ,
38- ) ,
39+ )
3940 ) ]
4041 #[ cfg_attr( feature = "serde" , serde( rename = "async" ) ) ]
4142 async_ : Vec < Async > ,
@@ -45,26 +46,35 @@ pub struct AsyncFilterSet {
4546 used_options : HashSet < usize > ,
4647}
4748
48- #[ cfg( feature = "clap" ) ]
49- fn parse_async ( s : & str ) -> Result < Async , String > {
50- Ok ( Async :: parse ( s) )
51- }
49+ impl FilterSet for AsyncFilterSet {
50+ type Mode = bool ;
51+ type Filter = AsyncFilter ;
5252
53- impl AsyncFilterSet {
54- /// Returns a set where all functions should be async or not depending on
55- /// `async_` provided.
56- pub fn all ( async_ : bool ) -> AsyncFilterSet {
57- AsyncFilterSet {
58- async_ : vec ! [ Async {
59- enabled: async_,
60- filter: AsyncFilter :: All ,
61- } ] ,
53+ fn new ( rules : Vec < Async > ) -> Self {
54+ Self {
55+ async_ : rules,
6256 used_options : HashSet :: new ( ) ,
6357 }
6458 }
6559
66- /// Returns whether the `func` provided is to be bound `async` or not.
67- pub fn is_async (
60+ fn rules ( & self ) -> & [ Async ] {
61+ & self . async_
62+ }
63+ fn rules_mut ( & mut self ) -> & mut Vec < Async > {
64+ & mut self . async_
65+ }
66+ fn used_options ( & self ) -> & HashSet < usize > {
67+ & self . used_options
68+ }
69+ fn used_options_mut ( & mut self ) -> & mut HashSet < usize > {
70+ & mut self . used_options
71+ }
72+
73+ fn option_name ( ) -> & ' static str {
74+ "async"
75+ }
76+
77+ fn apply_rules (
6878 & mut self ,
6979 resolve : & Resolve ,
7080 interface : Option < & WorldKey > ,
@@ -75,11 +85,12 @@ impl AsyncFilterSet {
7585 Some ( key) => format ! ( "{}#{}" , resolve. name_world_key( key) , func. name) ,
7686 None => func. name . clone ( ) ,
7787 } ;
88+
7889 for ( i, opt) in self . async_ . iter ( ) . enumerate ( ) {
7990 let name = match & opt. filter {
8091 AsyncFilter :: All => {
8192 self . used_options . insert ( i) ;
82- return opt. enabled ;
93+ return opt. mode ;
8394 }
8495 AsyncFilter :: Function ( s) => s,
8596 AsyncFilter :: Import ( s) => {
@@ -97,95 +108,77 @@ impl AsyncFilterSet {
97108 } ;
98109 if * name == name_to_test {
99110 self . used_options . insert ( i) ;
100- return opt. enabled ;
111+ return opt. mode ;
101112 }
102113 }
103114
104- match & func. kind {
105- FunctionKind :: Freestanding
106- | FunctionKind :: Method ( _)
107- | FunctionKind :: Static ( _)
108- | FunctionKind :: Constructor ( _) => false ,
115+ matches ! (
116+ func. kind,
109117 FunctionKind :: AsyncFreestanding
110- | FunctionKind :: AsyncMethod ( _)
111- | FunctionKind :: AsyncStatic ( _) => true ,
112- }
113- }
114-
115- /// Intended to be used in the header comment of generated code to help
116- /// indicate what options were specified.
117- pub fn debug_opts ( & self ) -> impl Iterator < Item = String > + ' _ {
118- self . async_ . iter ( ) . map ( |opt| opt. to_string ( ) )
118+ | FunctionKind :: AsyncMethod ( _)
119+ | FunctionKind :: AsyncStatic ( _)
120+ )
119121 }
122+ }
120123
121- /// Tests whether all `--async` options were used throughout bindings
122- /// generation, returning an error if any were unused.
123- pub fn ensure_all_used ( & self ) -> Result < ( ) > {
124- for ( i, opt) in self . async_ . iter ( ) . enumerate ( ) {
125- if self . used_options . contains ( & i) {
126- continue ;
127- }
128- if !matches ! ( opt. filter, AsyncFilter :: All ) {
129- bail ! ( "unused async option: {opt}" ) ;
130- }
131- }
132- Ok ( ( ) )
133- }
124+ #[ cfg( feature = "clap" ) ]
125+ fn parse_async ( s : & str ) -> Result < Async , String > {
126+ Ok ( Async :: parse ( s) )
127+ }
134128
135- /// Returns whether any option explicitly requests that async is enabled.
129+ impl AsyncFilterSet {
136130 pub fn any_enabled ( & self ) -> bool {
137- self . async_ . iter ( ) . any ( |o| o. enabled )
131+ self . async_ . iter ( ) . any ( |o| o. mode )
138132 }
133+ }
134+
135+ type Async = FilterRule < bool , AsyncFilter > ;
139136
140- /// Pushes a new option into this set.
141- pub fn push ( & mut self , directive : & str ) {
142- self . async_ . push ( Async :: parse ( directive) ) ;
137+ impl FilterMode for bool {
138+ fn parse ( s : & str ) -> ( Self , & str ) {
139+ match s. strip_prefix ( '-' ) {
140+ Some ( rest) => ( false , rest) ,
141+ None => ( true , s) ,
142+ }
143+ }
144+ fn fmt_prefix ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
145+ if * self {
146+ f. write_char ( '-' ) ?;
147+ }
148+ Ok ( ( ) )
143149 }
144150}
145151
146152#[ derive( Debug , Clone ) ]
147153#[ cfg_attr( feature = "serde" , derive( serde:: Deserialize ) ) ]
148- struct Async {
149- enabled : bool ,
150- filter : AsyncFilter ,
154+ pub enum AsyncFilter {
155+ All ,
156+ Function ( String ) ,
157+ Import ( String ) ,
158+ Export ( String ) ,
151159}
152160
153- impl Async {
154- fn parse ( s : & str ) -> Async {
155- let ( s, enabled) = match s. strip_prefix ( '-' ) {
156- Some ( s) => ( s, false ) ,
157- None => ( s, true ) ,
158- } ;
159- let filter = match s {
161+ impl FilterTarget for AsyncFilter {
162+ fn parse ( s : & str ) -> Self {
163+ match s {
160164 "all" => AsyncFilter :: All ,
161165 other => match other. strip_prefix ( "import:" ) {
162- Some ( s ) => AsyncFilter :: Import ( s . to_string ( ) ) ,
166+ Some ( sub ) => AsyncFilter :: Import ( sub . to_string ( ) ) ,
163167 None => match other. strip_prefix ( "export:" ) {
164- Some ( s ) => AsyncFilter :: Export ( s . to_string ( ) ) ,
165- None => AsyncFilter :: Function ( s . to_string ( ) ) ,
168+ Some ( sub ) => AsyncFilter :: Export ( sub . to_string ( ) ) ,
169+ None => AsyncFilter :: Function ( other . to_string ( ) ) ,
166170 } ,
167171 } ,
168- } ;
169- Async { enabled, filter }
172+ }
170173 }
171- }
172174
173- impl fmt:: Display for Async {
174- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
175- if !self . enabled {
176- write ! ( f, "-" ) ?;
177- }
178- self . filter . fmt ( f)
175+ fn all ( ) -> AsyncFilter {
176+ AsyncFilter :: All
179177 }
180- }
181178
182- #[ derive( Debug , Clone ) ]
183- #[ cfg_attr( feature = "serde" , derive( serde:: Deserialize ) ) ]
184- enum AsyncFilter {
185- All ,
186- Function ( String ) ,
187- Import ( String ) ,
188- Export ( String ) ,
179+ fn is_all ( & self ) -> bool {
180+ matches ! ( self , AsyncFilter :: All )
181+ }
189182}
190183
191184impl fmt:: Display for AsyncFilter {
0 commit comments