1
1
#![ recursion_limit = "1024" ]
2
2
3
3
use anyhow:: Context ;
4
- use clap:: builder:: { PossibleValue , TypedValueParser } ;
5
- use clap:: { Arg , Parser , ValueEnum } ;
4
+ use clap:: builder:: TypedValueParser ;
5
+ use clap:: { Arg , Parser } ;
6
6
use collector:: api:: next_artifact:: NextArtifact ;
7
7
use collector:: codegen:: { codegen_diff, CodegenType } ;
8
8
use collector:: compile:: benchmark:: category:: Category ;
@@ -22,6 +22,7 @@ use std::fs::File;
22
22
use std:: future:: Future ;
23
23
use std:: io:: BufWriter ;
24
24
use std:: io:: Write ;
25
+ use std:: marker:: PhantomData ;
25
26
use std:: path:: { Path , PathBuf } ;
26
27
use std:: process;
27
28
use std:: process:: Command ;
@@ -230,55 +231,24 @@ fn main() {
230
231
}
231
232
}
232
233
233
- #[ derive( Debug , Clone ) ]
234
- struct ProfileArg ( Vec < Profile > ) ;
234
+ /// We need to have a separate wrapper over a Vec<T>, otherwise Clap would incorrectly
235
+ /// assume that `EnumArgParser` parses a single item, rather than a list of items.
236
+ #[ derive( Clone , Debug ) ]
237
+ struct MultiEnumValue < T > ( Vec < T > ) ;
235
238
239
+ /// Parser for enums (like profile or scenario) which can be passed either as a comma-delimited
240
+ /// string or as the "All" string, which selects all variants.
236
241
#[ derive( Clone ) ]
237
- struct ProfileArgParser ;
242
+ struct EnumArgParser < T > ( PhantomData < T > ) ;
238
243
239
- /// We need to use a TypedValueParser to provide possible values help.
240
- /// If we just use `FromStr` + `#[arg(possible_values = [...])]`, `clap` will not allow passing
241
- /// multiple values.
242
- impl TypedValueParser for ProfileArgParser {
243
- type Value = ProfileArg ;
244
-
245
- fn parse_ref (
246
- & self ,
247
- cmd : & clap:: Command ,
248
- arg : Option < & Arg > ,
249
- value : & OsStr ,
250
- ) -> Result < Self :: Value , clap:: Error > {
251
- if value == "All" {
252
- Ok ( ProfileArg ( Profile :: all ( ) ) )
253
- } else {
254
- let profiles: Result < Vec < Profile > , _ > = value
255
- . to_str ( )
256
- . unwrap ( )
257
- . split ( ',' )
258
- . map ( |item| clap:: value_parser!( Profile ) . parse_ref ( cmd, arg, OsStr :: new ( item) ) )
259
- . collect ( ) ;
260
-
261
- Ok ( ProfileArg ( profiles?) )
262
- }
263
- }
264
-
265
- fn possible_values ( & self ) -> Option < Box < dyn Iterator < Item = PossibleValue > + ' _ > > {
266
- let values = Profile :: value_variants ( )
267
- . iter ( )
268
- . filter_map ( |item| item. to_possible_value ( ) )
269
- . chain ( [ PossibleValue :: new ( "All" ) ] ) ;
270
- Some ( Box :: new ( values) )
244
+ impl < T > Default for EnumArgParser < T > {
245
+ fn default ( ) -> Self {
246
+ Self ( Default :: default ( ) )
271
247
}
272
248
}
273
249
274
- #[ derive( Debug , Clone ) ]
275
- struct ScenarioArg ( Vec < Scenario > ) ;
276
-
277
- #[ derive( Clone ) ]
278
- struct ScenarioArgParser ;
279
-
280
- impl TypedValueParser for ScenarioArgParser {
281
- type Value = ScenarioArg ;
250
+ impl < T : clap:: ValueEnum + Sync + Send + ' static > TypedValueParser for EnumArgParser < T > {
251
+ type Value = MultiEnumValue < T > ;
282
252
283
253
fn parse_ref (
284
254
& self ,
@@ -287,26 +257,18 @@ impl TypedValueParser for ScenarioArgParser {
287
257
value : & OsStr ,
288
258
) -> Result < Self :: Value , clap:: Error > {
289
259
if value == "All" {
290
- Ok ( ScenarioArg ( Scenario :: all ( ) ) )
260
+ Ok ( MultiEnumValue ( T :: value_variants ( ) . to_vec ( ) ) )
291
261
} else {
292
- let scenarios : Result < Vec < Scenario > , _ > = value
262
+ let values : Result < Vec < T > , _ > = value
293
263
. to_str ( )
294
264
. unwrap ( )
295
265
. split ( ',' )
296
- . map ( |item| clap:: value_parser!( Scenario ) . parse_ref ( cmd, arg, OsStr :: new ( item) ) )
266
+ . map ( |item| clap:: value_parser!( T ) . parse_ref ( cmd, arg, OsStr :: new ( item) ) )
297
267
. collect ( ) ;
298
268
299
- Ok ( ScenarioArg ( scenarios ?) )
269
+ Ok ( MultiEnumValue ( values ?) )
300
270
}
301
271
}
302
-
303
- fn possible_values ( & self ) -> Option < Box < dyn Iterator < Item = PossibleValue > + ' _ > > {
304
- let values = Scenario :: value_variants ( )
305
- . iter ( )
306
- . filter_map ( |item| item. to_possible_value ( ) )
307
- . chain ( [ PossibleValue :: new ( "All" ) ] ) ;
308
- Some ( Box :: new ( values) )
309
- }
310
272
}
311
273
312
274
#[ derive( Debug , clap:: Parser ) ]
@@ -358,20 +320,20 @@ struct CompileTimeOptions {
358
320
#[ arg(
359
321
long = "profiles" ,
360
322
alias = "builds" , // the old name, for backward compatibility
361
- value_parser = ProfileArgParser ,
323
+ value_parser = EnumArgParser :: < Profile > :: default ( ) ,
362
324
// Don't run rustdoc by default
363
325
default_value = "Check,Debug,Opt" ,
364
326
) ]
365
- profiles : ProfileArg ,
327
+ profiles : MultiEnumValue < Profile > ,
366
328
367
329
/// Measure the scenarios in this comma-separated list
368
330
#[ arg(
369
331
long = "scenarios" ,
370
332
alias = "runs" , // the old name, for backward compatibility
371
- value_parser = ScenarioArgParser ,
333
+ value_parser = EnumArgParser :: < Scenario > :: default ( ) ,
372
334
default_value = "All"
373
335
) ]
374
- scenarios : ScenarioArg ,
336
+ scenarios : MultiEnumValue < Scenario > ,
375
337
376
338
/// The path to the local rustdoc to measure
377
339
#[ arg( long) ]
0 commit comments