windows_metadata/reader/
item_index.rs1use super::*;
2
3#[derive(Debug)]
4pub enum Item<'a> {
5 Type(TypeDef<'a>),
6 Fn(MethodDef<'a>),
7 Const(Field<'a>),
8}
9
10type HashType<'a> = HashMap<&'a str, HashMap<&'a str, Vec<Item<'a>>>>;
11
12pub struct ItemIndex<'a>(HashType<'a>);
13
14impl<'a> core::ops::Deref for ItemIndex<'a> {
15 type Target = HashType<'a>;
16
17 fn deref(&self) -> &HashType<'a> {
18 &self.0
19 }
20}
21
22impl<'a> ItemIndex<'a> {
23 pub fn new(index: &'a TypeIndex) -> Self {
24 let mut members: HashType = HashMap::new();
25
26 for (namespace, name, ty) in index.iter() {
27 let apis = !ty.flags().contains(TypeAttributes::WindowsRuntime)
28 && ty.category() == TypeCategory::Class
29 && name == "Apis";
30
31 if apis {
32 for method in ty.methods() {
33 insert(&mut members, namespace, method.name(), Item::Fn(method));
34 }
35 for field in ty.fields() {
36 insert(&mut members, namespace, field.name(), Item::Const(field));
37 }
38 } else {
39 insert(&mut members, namespace, name, Item::Type(ty));
40 }
41
42 if !ty.flags().contains(TypeAttributes::WindowsRuntime) {
44 match ty.category() {
45 TypeCategory::Enum if !ty.has_attribute("ScopedEnumAttribute") => {
46 for field in ty.fields() {
47 if field.flags().contains(FieldAttributes::Literal) {
48 insert(&mut members, namespace, field.name(), Item::Const(field));
49 }
50 }
51 }
52 _ => {}
53 }
54 }
55 }
56
57 Self(members)
58 }
59
60 pub fn iter(&self) -> impl Iterator<Item = (&str, &str, &Item<'_>)> + '_ {
61 self.0
62 .iter()
63 .flat_map(|(namespace, items)| {
64 items
65 .iter()
66 .map(move |(name, items)| (namespace, name, items))
67 })
68 .flat_map(|(namespace, name, items)| {
69 items.iter().map(move |item| (*namespace, *name, item))
70 })
71 }
72
73 pub fn items(&self) -> impl Iterator<Item = &Item<'_>> + '_ {
74 self.0.values().flat_map(|items| items.values()).flatten()
75 }
76
77 pub fn namespace_items(&self, namespace: &str) -> impl Iterator<Item = (&str, &Item<'_>)> + '_ {
78 self.0
79 .get(namespace)
80 .into_iter()
81 .flatten()
82 .flat_map(|(name, items)| items.iter().map(move |item| (*name, item)))
83 }
84
85 pub fn get(&self, namespace: &str, name: &str) -> impl Iterator<Item = &Item<'_>> + '_ {
86 self.0
87 .get(namespace)
88 .and_then(|items| items.get(name))
89 .into_iter()
90 .flatten()
91 }
92
93 #[track_caller]
94 pub fn expect(&self, namespace: &str, name: &str) -> &Item<'_> {
95 let mut iter = self.get(namespace, name);
96
97 if let Some(item) = iter.next() {
98 if iter.next().is_none() {
99 item
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
109fn insert<'a>(members: &mut HashType<'a>, namespace: &'a str, name: &'a str, member: Item<'a>) {
110 members
111 .entry(namespace)
112 .or_default()
113 .entry(name)
114 .or_default()
115 .push(member);
116}