Skip to content

Commit 9475a0a

Browse files
committed
Refactor module parsing function.
The logic of parsing a module macro is a little bit cumbersome and error-prone. Refactor this part to make it clear, concise, structural and extensible. Signed-off-by: d0u9 <d0u9.su@outlook.com>
1 parent 66893e3 commit 9475a0a

File tree

1 file changed

+67
-40
lines changed

1 file changed

+67
-40
lines changed

rust/macros/module.rs

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -313,17 +313,17 @@ impl ModuleInfo {
313313
fn parse(it: &mut token_stream::IntoIter) -> Self {
314314
let mut info = ModuleInfo::default();
315315

316-
const EXPECTED_KEYS: &[&str] = &[
317-
"type",
318-
"name",
319-
"author",
320-
"description",
321-
"license",
322-
"alias",
323-
"alias_rtnl_link",
324-
"params",
316+
const KEYS_AND_ACTIONS: &[(bool, &str, fn(&mut ModuleInfo, &mut token_stream::IntoIter))] = &[
317+
(true, "type", ModuleInfo::set_type),
318+
(true, "name", ModuleInfo::set_name),
319+
(false, "author", ModuleInfo::set_author),
320+
(false, "description", ModuleInfo::set_description),
321+
(true, "license", ModuleInfo::set_license),
322+
(false, "alias", ModuleInfo::set_alias),
323+
(false, "alias_rtnl_link", ModuleInfo::set_alias_rtnl_link),
324+
(false, "params", ModuleInfo::set_params),
325325
];
326-
const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
326+
327327
let mut seen_keys = Vec::new();
328328

329329
loop {
@@ -333,61 +333,88 @@ impl ModuleInfo {
333333
None => break,
334334
};
335335

336-
if seen_keys.contains(&key) {
336+
assert_eq!(expect_punct(it), ':');
337+
338+
let action = KEYS_AND_ACTIONS.iter()
339+
.find(|x| x.1 == key.as_str())
340+
.expect(format!("Unknown key \"{}\". Valid keys are: {:?}.",
341+
key,
342+
KEYS_AND_ACTIONS.iter()
343+
.map(|x| format!("{}, ", x.1.to_string()))
344+
.collect::<String>()
345+
).as_str());
346+
347+
if seen_keys.contains(&action.1) {
337348
panic!(
338349
"Duplicated key \"{}\". Keys can only be specified once.",
339350
key
340351
);
341-
}
342-
343-
assert_eq!(expect_punct(it), ':');
344-
345-
match key.as_str() {
346-
"type" => info.type_ = expect_ident(it),
347-
"name" => info.name = expect_byte_string(it),
348-
"author" => info.author = Some(expect_byte_string(it)),
349-
"description" => info.description = Some(expect_byte_string(it)),
350-
"license" => info.license = expect_byte_string(it),
351-
"alias" => info.alias = Some(expect_byte_string(it)),
352-
"alias_rtnl_link" => {
353-
info.alias = Some(format!("rtnl-link-{}", expect_byte_string(it)))
354-
}
355-
"params" => info.params = Some(expect_group(it)),
356-
_ => panic!(
357-
"Unknown key \"{}\". Valid keys are: {:?}.",
358-
key, EXPECTED_KEYS
359-
),
352+
} else {
353+
action.2(&mut info, it);
360354
}
361355

362356
assert_eq!(expect_punct(it), ',');
363357

364-
seen_keys.push(key);
358+
seen_keys.push(&action.1);
365359
}
366360

367361
expect_end(it);
368362

369-
for key in REQUIRED_KEYS {
370-
if !seen_keys.iter().any(|e| e == key) {
371-
panic!("Missing required key \"{}\".", key);
363+
let mut ordered_keys: Vec<&str> = Vec::new();
364+
for action in KEYS_AND_ACTIONS.iter() {
365+
let has_key = seen_keys.iter().any(|e| e == &action.1);
366+
if action.0 && !has_key {
367+
panic!("Missing required key \"{}\".", action.1);
372368
}
373-
}
374369

375-
let mut ordered_keys: Vec<&str> = Vec::new();
376-
for key in EXPECTED_KEYS {
377-
if seen_keys.iter().any(|e| e == key) {
378-
ordered_keys.push(key);
370+
if has_key {
371+
ordered_keys.push(&action.1);
379372
}
380373
}
381374

382375
if seen_keys != ordered_keys {
383376
panic!(
384377
"Keys are not ordered as expected. Order them like: {:?}.",
385-
ordered_keys
378+
ordered_keys,
386379
);
387380
}
388381

382+
389383
info
390384
}
385+
386+
fn set_name(&mut self, it: &mut token_stream::IntoIter) {
387+
self.name = expect_byte_string(it);
388+
}
389+
390+
fn set_type(&mut self, it: &mut token_stream::IntoIter) {
391+
self.type_ = expect_ident(it);
392+
}
393+
394+
fn set_license(&mut self, it: &mut token_stream::IntoIter) {
395+
self.license = expect_byte_string(it);
396+
}
397+
398+
fn set_author(&mut self, it: &mut token_stream::IntoIter) {
399+
self.author = Some(expect_byte_string(it));
400+
}
401+
402+
fn set_description(&mut self, it: &mut token_stream::IntoIter) {
403+
self.description = Some(expect_byte_string(it));
404+
}
405+
406+
fn set_alias(&mut self, it: &mut token_stream::IntoIter) {
407+
self.alias = Some(expect_byte_string(it))
408+
}
409+
410+
fn set_alias_rtnl_link(&mut self, it: &mut token_stream::IntoIter) {
411+
self.alias = Some(format!("rtnl-link-{}", expect_byte_string(it)))
412+
}
413+
414+
fn set_params(&mut self, it: &mut token_stream::IntoIter) {
415+
self.params = Some(expect_group(it))
416+
}
417+
391418
}
392419

393420
pub fn module(ts: TokenStream) -> TokenStream {

0 commit comments

Comments
 (0)