/
merge_extern_blocks.rs
51 lines (47 loc) · 1.71 KB
/
merge_extern_blocks.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use syn::{Item, ItemForeignMod};
use crate::BindgenOptions;
pub(super) fn merge_extern_blocks(
items: &mut Vec<Item>,
_options: &BindgenOptions,
) {
// Keep all the extern blocks in a different `Vec` for faster search.
let mut foreign_mods = Vec::<ItemForeignMod>::new();
for item in std::mem::take(items) {
match item {
Item::ForeignMod(ItemForeignMod {
attrs,
abi,
brace_token,
items: foreign_items,
}) => {
let mut exists = false;
for foreign_mod in &mut foreign_mods {
// Check if there is a extern block with the same ABI and
// attributes.
if foreign_mod.attrs == attrs && foreign_mod.abi == abi {
// Merge the items of the two blocks.
foreign_mod.items.extend_from_slice(&foreign_items);
exists = true;
break;
}
}
// If no existing extern block had the same ABI and attributes, store
// it.
if !exists {
foreign_mods.push(ItemForeignMod {
attrs,
abi,
brace_token,
items: foreign_items,
});
}
}
// If the item is not an extern block, we don't have to do anything.
_ => items.push(item),
}
}
// Move all the extern blocks alongside the rest of the items.
for foreign_mod in foreign_mods {
items.push(Item::ForeignMod(foreign_mod));
}
}