windows_metadata/reader/
index.rs

1use 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                    // Skips `<Module>` as well as nested types.
24                    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}