windows_metadata/reader/
index.rs1use super::*;
2
3pub struct Index {
4 files: Vec<File>,
5 types: HashMap<String, HashMap<String, Vec<(usize, usize)>>>,
6 nested: HashMap<(usize, usize), Vec<usize>>,
7}
8
9impl Index {
10 pub fn read<P: AsRef<std::path::Path>>(path: P) -> Option<Self> {
11 Some(Self::new(vec![File::read(path)?]))
12 }
13
14 pub fn new(files: Vec<File>) -> Self {
15 let mut types: HashMap<String, HashMap<String, Vec<(usize, usize)>>> = HashMap::new();
16 let mut nested: HashMap<(usize, usize), Vec<usize>> = HashMap::new();
17
18 for (file_pos, file) in files.iter().enumerate() {
19 for def_pos in file.TypeDef() {
20 let namespace = file.str(def_pos, TypeDef::TABLE, 2);
21
22 if namespace.is_empty() {
23 continue;
25 }
26
27 let name = file.str(def_pos, TypeDef::TABLE, 1);
28
29 types
30 .entry(namespace.to_string())
31 .or_default()
32 .entry(trim_tick(name).to_string())
33 .or_default()
34 .push((file_pos, def_pos));
35 }
36
37 for map in file.NestedClass() {
38 let inner = file.usize(map, TypeDef::TABLE, 0);
39 let outer = file.usize(map, TypeDef::TABLE, 1);
40 nested.entry((file_pos, outer)).or_default().push(inner);
41 }
42 }
43
44 Self {
45 files,
46 types,
47 nested,
48 }
49 }
50
51 pub(crate) fn files(&self, pos: usize) -> &File {
52 &self.files[pos]
53 }
54
55 pub fn all(&self) -> impl Iterator<Item = TypeDef> + '_ {
56 self.types
57 .values()
58 .flat_map(|types| types.values())
59 .flatten()
60 .map(|(file, pos)| TypeDef(Row::new(self, *file, *pos)))
61 }
62
63 pub fn get(&self, namespace: &str, name: &str) -> impl Iterator<Item = TypeDef> + '_ {
64 self.types
65 .get(namespace)
66 .and_then(|types| types.get(name))
67 .into_iter()
68 .flatten()
69 .map(|(file, pos)| TypeDef(Row::new(self, *file, *pos)))
70 }
71
72 pub fn expect(&self, namespace: &str, name: &str) -> TypeDef {
73 let mut iter = self.get(namespace, name);
74
75 if let Some(def) = iter.next() {
76 if iter.next().is_none() {
77 def
78 } else {
79 panic!("more than one type found: {namespace}.{name}");
80 }
81 } else {
82 panic!("type not found: {namespace}.{name}")
83 }
84 }
85
86 pub fn nested(&self, ty: TypeDef) -> impl Iterator<Item = TypeDef> + '_ {
87 self.nested
88 .get(&(ty.0.file, ty.0.pos))
89 .into_iter()
90 .flatten()
91 .cloned()
92 .map(move |pos| {
93 TypeDef(Row {
94 index: self,
95 file: ty.0.file,
96 pos,
97 })
98 })
99 }
100}