Skip to main content

windows_metadata/reader/
type_index.rs

1use super::*;
2
3pub struct TypeIndex {
4    files: Vec<File>,
5    types: HashMap<String, HashMap<String, Vec<(usize, usize)>>>,
6    nested: HashMap<(usize, usize), Vec<usize>>,
7}
8
9impl TypeIndex {
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, NestedClass::TABLE, 0) - 1;
39                let outer = file.usize(map, NestedClass::TABLE, 1) - 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 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<'_>> + '_ {
70        self.types
71            .values()
72            .flat_map(|types| types.values())
73            .flatten()
74            .map(|(file, pos)| TypeDef(Row::new(self, *file, *pos)))
75    }
76
77    pub fn get(&self, namespace: &str, name: &str) -> impl Iterator<Item = TypeDef<'_>> + '_ {
78        self.types
79            .get(namespace)
80            .and_then(|types| types.get(name))
81            .into_iter()
82            .flatten()
83            .map(|(file, pos)| TypeDef(Row::new(self, *file, *pos)))
84    }
85
86    pub fn contains(&self, namespace: &str, name: &str) -> bool {
87        self.types
88            .get(namespace)
89            .and_then(|types| types.get(name))
90            .is_some()
91    }
92
93    #[track_caller]
94    pub fn expect(&self, namespace: &str, name: &str) -> TypeDef<'_> {
95        let mut iter = self.get(namespace, name);
96
97        if let Some(def) = iter.next() {
98            if iter.next().is_none() {
99                def
100            } else {
101                panic!("more than one type found: {namespace}.{name}");
102            }
103        } else {
104            panic!("type not found: {namespace}.{name}")
105        }
106    }
107
108    pub fn nested(&self, ty: TypeDef) -> impl Iterator<Item = TypeDef<'_>> + '_ {
109        self.nested
110            .get(&(ty.0.file, ty.0.pos))
111            .into_iter()
112            .flatten()
113            .cloned()
114            .map(move |pos| {
115                TypeDef(Row {
116                    index: self,
117                    file: ty.0.file,
118                    pos,
119                })
120            })
121    }
122}