@@ -321,81 +321,82 @@ struct ModuleInfo {
321
321
impl ModuleInfo {
322
322
fn parse ( it : & mut token_stream:: IntoIter ) -> Self {
323
323
let mut info = ModuleInfo :: default ( ) ;
324
- // The first allowed position is 1, to prevent setting something twice.
325
- let mut pos = 0u8 ;
324
+
325
+ const EXPECTED_KEYS : & [ & str ] = & [
326
+ "type" ,
327
+ "name" ,
328
+ "author" ,
329
+ "description" ,
330
+ "license" ,
331
+ "alias" ,
332
+ "alias_rtnl_link" ,
333
+ "params" ,
334
+ ] ;
335
+ const REQUIRED_KEYS : & [ & str ] = & [ "type" , "name" , "license" ] ;
336
+ let mut seen_keys = Vec :: new ( ) ;
326
337
327
338
loop {
328
- let name = match it. next ( ) {
339
+ let key = match it. next ( ) {
329
340
Some ( TokenTree :: Ident ( ident) ) => ident. to_string ( ) ,
330
341
Some ( _) => panic ! ( "Expected Ident or end" ) ,
331
342
None => break ,
332
343
} ;
333
344
345
+ if seen_keys. contains ( & key) {
346
+ panic ! (
347
+ "Duplicated key \" {}\" . Keys can only be specified once." ,
348
+ key
349
+ ) ;
350
+ }
351
+
334
352
assert_eq ! ( expect_punct( it) , ':' ) ;
335
353
336
- if name == "type" {
337
- Self :: allowed_pos ( & mut pos, 1 , & name) ;
338
- let type_ = expect_ident ( it) ;
339
- info. type_ = type_;
340
- } else if name == "params" {
341
- Self :: allowed_pos ( & mut pos, 7 , & name) ;
342
- let params = expect_group ( it) ;
343
- info. params = Some ( params) ;
344
- } else {
345
- let value = expect_byte_string ( it) ;
346
-
347
- match name. as_str ( ) {
348
- "name" => {
349
- Self :: allowed_pos ( & mut pos, 2 , & name) ;
350
- info. name = value;
351
- }
352
- "author" => {
353
- Self :: allowed_pos ( & mut pos, 3 , & name) ;
354
- info. author = Some ( value) ;
355
- }
356
- "description" => {
357
- Self :: allowed_pos ( & mut pos, 4 , & name) ;
358
- info. description = Some ( value) ;
359
- }
360
- "license" => {
361
- Self :: allowed_pos ( & mut pos, 5 , & name) ;
362
- info. license = value;
363
- }
364
- "alias" => {
365
- Self :: allowed_pos ( & mut pos, 6 , & name) ;
366
- info. alias = Some ( value) ;
367
- }
368
- "alias_rtnl_link" => {
369
- Self :: allowed_pos ( & mut pos, 6 , & name) ;
370
- info. alias = Some ( format ! ( "rtnl-link-{}" , value) ) ;
371
- }
372
- _ => panic ! ( "field '{}' is not supported by module" , name) ,
354
+ match key. as_str ( ) {
355
+ "type" => info. type_ = expect_ident ( it) ,
356
+ "name" => info. name = expect_byte_string ( it) ,
357
+ "author" => info. author = Some ( expect_byte_string ( it) ) ,
358
+ "description" => info. description = Some ( expect_byte_string ( it) ) ,
359
+ "license" => info. license = expect_byte_string ( it) ,
360
+ "alias" => info. alias = Some ( expect_byte_string ( it) ) ,
361
+ "alias_rtnl_link" => {
362
+ info. alias = Some ( format ! ( "rtnl-link-{}" , expect_byte_string( it) ) )
373
363
}
364
+ "params" => info. params = Some ( expect_group ( it) ) ,
365
+ _ => panic ! (
366
+ "Unknown key \" {}\" . Valid keys are: {:?}." ,
367
+ key, EXPECTED_KEYS
368
+ ) ,
374
369
}
370
+
375
371
assert_eq ! ( expect_punct( it) , ',' ) ;
372
+
373
+ seen_keys. push ( key) ;
376
374
}
377
375
378
376
expect_end ( it) ;
379
377
380
- if info. type_ . is_empty ( ) {
381
- panic ! ( "'type' not specified in module macro" ) ;
378
+ for key in REQUIRED_KEYS {
379
+ if !seen_keys. iter ( ) . any ( |e| e == key) {
380
+ panic ! ( "Missing required key \" {}\" ." , key) ;
381
+ }
382
382
}
383
- if info. license . is_empty ( ) {
384
- panic ! ( "'license' not specified in module macro" ) ;
383
+
384
+ let mut ordered_keys: Vec < & str > = Vec :: new ( ) ;
385
+ for key in EXPECTED_KEYS {
386
+ if seen_keys. iter ( ) . any ( |e| e == key) {
387
+ ordered_keys. push ( key) ;
388
+ }
385
389
}
386
- if info. name . is_empty ( ) {
387
- panic ! ( "'name' not specified in module macro" ) ;
390
+
391
+ if seen_keys != ordered_keys {
392
+ panic ! (
393
+ "Keys are not ordered as expected. Order them like: {:?}." ,
394
+ ordered_keys
395
+ ) ;
388
396
}
389
397
390
398
info
391
399
}
392
-
393
- fn allowed_pos ( pos : & mut u8 , allowed_pos : u8 , name : & str ) {
394
- if * pos > allowed_pos {
395
- panic ! ( "'{}' is not allowed at this position" , name) ;
396
- }
397
- * pos = allowed_pos;
398
- }
399
400
}
400
401
401
402
/// Declares a kernel module.
0 commit comments