Skip to content

Commit 4bf3257

Browse files
committed
item_index
1 parent 6d775b9 commit 4bf3257

File tree

15 files changed

+187
-37
lines changed

15 files changed

+187
-37
lines changed

crates/libs/metadata/src/reader/blob.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::*;
22

33
pub struct Blob<'a> {
4-
index: &'a Index,
4+
index: &'a TypeIndex,
55
file: usize,
66
slice: &'a [u8],
77
}
@@ -27,7 +27,7 @@ impl std::ops::Deref for Blob<'_> {
2727
}
2828

2929
impl<'a> Blob<'a> {
30-
pub fn new(index: &'a Index, file: usize, slice: &'a [u8]) -> Self {
30+
pub fn new(index: &'a TypeIndex, file: usize, slice: &'a [u8]) -> Self {
3131
Self { index, file, slice }
3232
}
3333

crates/libs/metadata/src/reader/codes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::*;
22

33
pub trait Decode<'a> {
4-
fn decode(index: &'a Index, file: usize, code: usize) -> Self;
4+
fn decode(index: &'a TypeIndex, file: usize, code: usize) -> Self;
55
}
66

77
macro_rules! code {
@@ -11,7 +11,7 @@ macro_rules! code {
1111
$($table($table<'a>),)*
1212
}
1313
impl<'a> Decode<'a> for $name<'a> {
14-
fn decode(index: &'a Index, file: usize, code: usize) -> Self {
14+
fn decode(index: &'a TypeIndex, file: usize, code: usize) -> Self {
1515
let (kind, row) = (code & ((1 << $size) - 1), (code >> $size) - 1);
1616
match kind {
1717
$($code => Self::$table($table(Row::new(index, file, row))),)*
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use super::*;
2+
3+
pub enum Item<'a> {
4+
Type(TypeDef<'a>),
5+
Fn(MethodDef<'a>),
6+
Const(Field<'a>),
7+
}
8+
9+
type HashType<'a> = HashMap<&'a str, HashMap<&'a str, Vec<Item<'a>>>>;
10+
11+
pub struct ItemIndex<'a>(HashType<'a>);
12+
13+
impl<'a> ItemIndex<'a> {
14+
pub fn new(index: &'a TypeIndex) -> Self {
15+
let mut members: HashType = HashMap::new();
16+
17+
for (namespace, name, ty) in index.iter() {
18+
insert(&mut members, namespace, name, Item::Type(ty));
19+
20+
if !ty.flags().contains(TypeAttributes::WindowsRuntime) {
21+
match ty.category() {
22+
TypeCategory::Class if name == "Apis" => {
23+
for method in ty.methods() {
24+
insert(&mut members, namespace, method.name(), Item::Fn(method));
25+
}
26+
for field in ty.fields() {
27+
insert(&mut members, namespace, field.name(), Item::Const(field));
28+
}
29+
}
30+
TypeCategory::Enum if !ty.has_attribute("ScopedEnumAttribute") => {
31+
for field in ty.fields() {
32+
if field.flags().contains(FieldAttributes::Literal) {
33+
insert(&mut members, namespace, field.name(), Item::Const(field));
34+
}
35+
}
36+
}
37+
_ => {}
38+
}
39+
}
40+
}
41+
42+
Self(members)
43+
}
44+
45+
pub fn iter(&self) -> impl Iterator<Item = (&str, &str, &Item)> + '_ {
46+
self.0
47+
.iter()
48+
.flat_map(|(namespace, items)| {
49+
items
50+
.iter()
51+
.map(move |(name, items)| (namespace, name, items))
52+
})
53+
.flat_map(|(namespace, name, items)| {
54+
items.iter().map(move |item| (*namespace, *name, item))
55+
})
56+
}
57+
58+
pub fn items(&self) -> impl Iterator<Item = &Item> + '_ {
59+
self.0.values().flat_map(|items| items.values()).flatten()
60+
}
61+
62+
pub fn get(&self, namespace: &str, name: &str) -> impl Iterator<Item = &Item> + '_ {
63+
self.0
64+
.get(namespace)
65+
.and_then(|items| items.get(name))
66+
.into_iter()
67+
.flatten()
68+
}
69+
70+
#[track_caller]
71+
pub fn expect(&self, namespace: &str, name: &str) -> &Item {
72+
let mut iter = self.get(namespace, name);
73+
74+
if let Some(item) = iter.next() {
75+
if iter.next().is_none() {
76+
item
77+
} else {
78+
panic!("more than one type found: {namespace}.{name}");
79+
}
80+
} else {
81+
panic!("type not found: {namespace}.{name}")
82+
}
83+
}
84+
}
85+
86+
fn insert<'a>(members: &mut HashType<'a>, namespace: &'a str, name: &'a str, member: Item<'a>) {
87+
members
88+
.entry(namespace)
89+
.or_default()
90+
.entry(name)
91+
.or_default()
92+
.push(member);
93+
}

crates/libs/metadata/src/reader/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ use super::*;
33
mod blob;
44
mod codes;
55
mod file;
6-
mod index;
6+
mod item_index;
77
mod row;
88
mod tables;
99
mod type_category;
10+
mod type_index;
1011

1112
pub use blob::*;
1213
pub use codes::*;
1314
pub use file::*;
14-
pub use index::*;
15+
pub use item_index::*;
1516
pub use row::*;
1617
pub use tables::*;
1718
pub use type_category::*;
19+
pub use type_index::*;
1820

1921
fn trim_tick(name: &str) -> &str {
2022
if name.as_bytes().iter().rev().nth(1) == Some(&b'`') {

crates/libs/metadata/src/reader/row.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::*;
22

33
#[derive(Copy, Clone)]
44
pub struct Row<'a> {
5-
pub index: &'a Index,
5+
pub index: &'a TypeIndex,
66
pub file: usize,
77
pub pos: usize,
88
}
@@ -47,7 +47,7 @@ unsafe impl Send for Row<'_> {}
4747
unsafe impl Sync for Row<'_> {}
4848

4949
impl<'a> Row<'a> {
50-
pub(crate) fn new(index: &'a Index, file: usize, pos: usize) -> Self {
50+
pub(crate) fn new(index: &'a TypeIndex, file: usize, pos: usize) -> Self {
5151
Self { index, file, pos }
5252
}
5353
}
@@ -57,7 +57,7 @@ pub trait AsRow<'a>: Copy {
5757
fn to_row(&self) -> Row<'a>;
5858
fn from_row(row: Row<'a>) -> Self;
5959

60-
fn index(&self) -> &'a Index {
60+
fn index(&self) -> &'a TypeIndex {
6161
let row = self.to_row();
6262
row.index
6363
}
@@ -129,14 +129,14 @@ pub trait AsRow<'a>: Copy {
129129
}
130130

131131
pub struct RowIterator<'a, R: AsRow<'a>> {
132-
index: &'a Index,
132+
index: &'a TypeIndex,
133133
file: usize,
134134
rows: std::ops::Range<usize>,
135135
phantom: std::marker::PhantomData<R>,
136136
}
137137

138138
impl<'a, R: AsRow<'a>> RowIterator<'a, R> {
139-
pub(crate) fn new(index: &'a Index, file: usize, rows: std::ops::Range<usize>) -> Self {
139+
pub(crate) fn new(index: &'a TypeIndex, file: usize, rows: std::ops::Range<usize>) -> Self {
140140
Self {
141141
index,
142142
file,

crates/libs/metadata/src/reader/tables/field.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ impl std::fmt::Debug for Field<'_> {
66
}
77
}
88

9-
impl Field<'_> {
9+
impl<'a> Field<'a> {
1010
pub fn flags(&self) -> FieldAttributes {
1111
FieldAttributes(self.usize(0).try_into().unwrap())
1212
}
1313

14-
pub fn name(&self) -> &str {
14+
pub fn name(&self) -> &'a str {
1515
self.str(1)
1616
}
1717

crates/libs/metadata/src/reader/tables/method_def.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ impl std::fmt::Debug for MethodDef<'_> {
66
}
77
}
88

9-
impl MethodDef<'_> {
9+
impl<'a> MethodDef<'a> {
1010
pub fn rva(&self) -> usize {
1111
self.usize(0)
1212
}
@@ -19,7 +19,7 @@ impl MethodDef<'_> {
1919
MethodAttributes(self.usize(2).try_into().unwrap())
2020
}
2121

22-
pub fn name(&self) -> &str {
22+
pub fn name(&self) -> &'a str {
2323
self.str(3)
2424
}
2525

crates/libs/metadata/src/reader/tables/type_def.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ impl std::fmt::Debug for TypeDef<'_> {
66
}
77
}
88

9-
impl TypeDef<'_> {
9+
impl<'a> TypeDef<'a> {
1010
pub fn flags(&self) -> TypeAttributes {
1111
TypeAttributes(self.usize(0).try_into().unwrap())
1212
}
1313

14-
pub fn name(&self) -> &str {
14+
pub fn name(&self) -> &'a str {
1515
self.str(1)
1616
}
1717

18-
pub fn namespace(&self) -> &str {
18+
pub fn namespace(&self) -> &'a str {
1919
self.str(2)
2020
}
2121

@@ -27,11 +27,11 @@ impl TypeDef<'_> {
2727
Some(self.decode(3))
2828
}
2929

30-
pub fn fields(&self) -> RowIterator<Field> {
30+
pub fn fields(&self) -> RowIterator<'a, Field<'a>> {
3131
self.list(4)
3232
}
3333

34-
pub fn methods(&self) -> RowIterator<MethodDef> {
34+
pub fn methods(&self) -> RowIterator<'a, MethodDef<'a>> {
3535
self.list(5)
3636
}
3737

crates/libs/metadata/src/reader/index.rs renamed to crates/libs/metadata/src/reader/type_index.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use super::*;
22

3-
pub struct Index {
3+
pub struct TypeIndex {
44
files: Vec<File>,
55
types: HashMap<String, HashMap<String, Vec<(usize, usize)>>>,
66
nested: HashMap<(usize, usize), Vec<usize>>,
77
}
88

9-
impl Index {
9+
impl TypeIndex {
1010
pub fn read<P: AsRef<std::path::Path>>(path: P) -> Option<Self> {
1111
Some(Self::new(vec![File::read(path)?]))
1212
}
@@ -52,7 +52,21 @@ impl Index {
5252
&self.files[pos]
5353
}
5454

55-
pub fn all(&self) -> impl Iterator<Item = TypeDef> + '_ {
55+
pub fn iter(&self) -> impl Iterator<Item = (&str, &str, TypeDef)> + '_ {
56+
self.types
57+
.iter()
58+
.flat_map(|(namespace, types)| {
59+
types
60+
.iter()
61+
.map(move |(name, types)| (namespace.as_str(), name.as_str(), types))
62+
})
63+
.flat_map(|(namespace, name, types)| types.iter().map(move |ty| (namespace, name, ty)))
64+
.map(|(namespace, name, (file, pos))| {
65+
(namespace, name, TypeDef(Row::new(self, *file, *pos)))
66+
})
67+
}
68+
69+
pub fn types(&self) -> impl Iterator<Item = TypeDef> + '_ {
5670
self.types
5771
.values()
5872
.flat_map(|types| types.values())
@@ -69,6 +83,7 @@ impl Index {
6983
.map(|(file, pos)| TypeDef(Row::new(self, *file, *pos)))
7084
}
7185

86+
#[track_caller]
7287
pub fn expect(&self, namespace: &str, name: &str) -> TypeDef {
7388
let mut iter = self.get(namespace, name);
7489

crates/tests/libs/metadata/tests/attribute.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ fn test() {
6060
let bytes = file.into_stream();
6161
std::fs::write("tests/attribute.winmd", bytes).unwrap();
6262

63-
let reader = reader::Index::read("tests/attribute.winmd").unwrap();
64-
let ty = reader.expect("Namespace", "Name");
63+
let index = reader::TypeIndex::read("tests/attribute.winmd").unwrap();
64+
let ty = index.expect("Namespace", "Name");
6565

6666
let attributes: Vec<_> = ty.attributes().collect();
6767
assert_eq!(attributes.len(), 1);

crates/tests/libs/metadata/tests/class.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,6 @@ fn test() {
8383
let bytes = file.into_stream();
8484
std::fs::write("tests/class.winmd", bytes).unwrap();
8585

86-
let reader = reader::Index::read("tests/class.winmd").unwrap();
87-
let _ty = reader.expect("Namespace", "Name");
86+
let index = reader::TypeIndex::read("tests/class.winmd").unwrap();
87+
let _ty = index.expect("Namespace", "Name");
8888
}

crates/tests/libs/metadata/tests/empty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ fn test() {
66
let bytes = file.into_stream();
77
std::fs::write("tests/empty.winmd", bytes).unwrap();
88

9-
let _reader = reader::Index::read("tests/empty.winmd").unwrap();
9+
let _index = reader::TypeIndex::read("tests/empty.winmd").unwrap();
1010
}

crates/tests/libs/metadata/tests/interface.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ fn test() {
4141
let bytes = file.into_stream();
4242
std::fs::write("tests/interface.winmd", bytes).unwrap();
4343

44-
let reader = reader::Index::read("tests/interface.winmd").unwrap();
45-
let ty = reader.expect("Namespace", "Name");
44+
let index = reader::TypeIndex::read("tests/interface.winmd").unwrap();
45+
let ty = index.expect("Namespace", "Name");
4646

4747
let methods: Vec<_> = ty.methods().collect();
4848
assert_eq!(methods.len(), 2);

0 commit comments

Comments
 (0)