| 1 | use super::*; |
| 2 | |
| 3 | fn insert(types: &mut HashMap<&'static str, Vec<Type>>, name: &'static str, ty: Type) { |
| 4 | types.entry(key:name).or_default().push(ty); |
| 5 | } |
| 6 | |
| 7 | pub struct Reader(HashMap<&'static str, HashMap<&'static str, Vec<Type>>>); |
| 8 | |
| 9 | impl std::ops::Deref for Reader { |
| 10 | type Target = HashMap<&'static str, HashMap<&'static str, Vec<Type>>>; |
| 11 | |
| 12 | fn deref(&self) -> &Self::Target { |
| 13 | &self.0 |
| 14 | } |
| 15 | } |
| 16 | |
| 17 | impl Reader { |
| 18 | pub fn new(files: Vec<File>) -> &'static Self { |
| 19 | let reader = Box::leak(Box::new(Self(HashMap::new()))); |
| 20 | |
| 21 | for mut file in files { |
| 22 | file.reader = reader; |
| 23 | let file = Box::leak(Box::new(file)); |
| 24 | let mut nested = HashMap::<TypeDef, Vec<TypeDef>>::new(); |
| 25 | |
| 26 | for key in file.table::<NestedClass>() { |
| 27 | let inner = key.inner(); |
| 28 | nested.entry(key.outer()).or_default().push(inner); |
| 29 | } |
| 30 | |
| 31 | for def in file.table::<TypeDef>() { |
| 32 | let type_name = def.type_name(); |
| 33 | |
| 34 | if type_name.namespace().is_empty() { |
| 35 | // This skips the nested types as we've already retrieved them. |
| 36 | continue; |
| 37 | } |
| 38 | |
| 39 | if Type::remap(type_name) != Remap::None { |
| 40 | continue; |
| 41 | } |
| 42 | |
| 43 | let types = reader.0.entry(type_name.namespace()).or_default(); |
| 44 | let category = Category::new(def); |
| 45 | |
| 46 | if def.flags().contains(TypeAttributes::WindowsRuntime) { |
| 47 | let ty = match category { |
| 48 | Category::Attribute => continue, |
| 49 | Category::Class => Type::Class(Class { def }), |
| 50 | Category::Delegate => Type::Delegate(Delegate { |
| 51 | def, |
| 52 | generics: def.generics(), |
| 53 | }), |
| 54 | Category::Enum => Type::Enum(Enum { def }), |
| 55 | Category::Interface => Type::Interface(Interface { |
| 56 | def, |
| 57 | generics: def.generics(), |
| 58 | kind: InterfaceKind::None, |
| 59 | }), |
| 60 | Category::Struct => { |
| 61 | // Skip marker types representing API contracts. |
| 62 | if def.has_attribute("ApiContractAttribute" ) { |
| 63 | continue; |
| 64 | } |
| 65 | |
| 66 | Type::Struct(Struct { def }) |
| 67 | } |
| 68 | }; |
| 69 | |
| 70 | insert(types, type_name.1, ty); |
| 71 | } else { |
| 72 | match category { |
| 73 | Category::Attribute => continue, |
| 74 | Category::Class => { |
| 75 | if type_name.1 == "Apis" { |
| 76 | for method in def.methods() { |
| 77 | if let Some(map) = method.impl_map() { |
| 78 | // Skip inline and ordinal functions. |
| 79 | if map.scope().name() == "FORCEINLINE" |
| 80 | || map.import_name().starts_with("#" ) |
| 81 | { |
| 82 | continue; |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | let name = method.name(); |
| 87 | insert( |
| 88 | types, |
| 89 | name, |
| 90 | Type::CppFn(CppFn { |
| 91 | namespace: def.namespace(), |
| 92 | method, |
| 93 | }), |
| 94 | ); |
| 95 | } |
| 96 | |
| 97 | for field in def.fields() { |
| 98 | let name = field.name(); |
| 99 | insert( |
| 100 | types, |
| 101 | name, |
| 102 | Type::CppConst(CppConst { |
| 103 | namespace: def.namespace(), |
| 104 | field, |
| 105 | }), |
| 106 | ); |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | Category::Delegate => { |
| 111 | insert(types, type_name.1, Type::CppDelegate(CppDelegate { def })); |
| 112 | } |
| 113 | Category::Enum => { |
| 114 | insert(types, type_name.1, Type::CppEnum(CppEnum { def })); |
| 115 | |
| 116 | if !def.has_attribute("ScopedEnumAttribute" ) { |
| 117 | for field in def.fields() { |
| 118 | if field.flags().contains(FieldAttributes::Literal) { |
| 119 | let name = field.name(); |
| 120 | insert( |
| 121 | types, |
| 122 | name, |
| 123 | Type::CppConst(CppConst { |
| 124 | namespace: def.namespace(), |
| 125 | field, |
| 126 | }), |
| 127 | ); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | Category::Interface => { |
| 133 | insert(types, type_name.1, Type::CppInterface(CppInterface { def })); |
| 134 | } |
| 135 | Category::Struct => { |
| 136 | fn make( |
| 137 | def: TypeDef, |
| 138 | name: &'static str, |
| 139 | nested: &HashMap<TypeDef, Vec<TypeDef>>, |
| 140 | ) -> CppStruct { |
| 141 | let mut ty = CppStruct { |
| 142 | def, |
| 143 | name, |
| 144 | nested: BTreeMap::new(), |
| 145 | }; |
| 146 | |
| 147 | for (index, def) in |
| 148 | nested.get(&def).into_iter().flatten().enumerate() |
| 149 | { |
| 150 | ty.nested.insert( |
| 151 | def.name(), |
| 152 | make(*def, format!(" {}_ {index}" , ty.name).leak(), nested), |
| 153 | ); |
| 154 | } |
| 155 | |
| 156 | ty |
| 157 | } |
| 158 | |
| 159 | insert( |
| 160 | types, |
| 161 | type_name.1, |
| 162 | Type::CppStruct(make(def, def.name(), &nested)), |
| 163 | ); |
| 164 | } |
| 165 | }; |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | reader |
| 171 | } |
| 172 | |
| 173 | #[track_caller ] |
| 174 | pub fn unwrap_full_name(&self, namespace: &str, name: &str) -> Type { |
| 175 | if let Some(ty) = self.with_full_name(namespace, name).next() { |
| 176 | ty |
| 177 | } else { |
| 178 | panic!("type not found: {namespace}. {name}" ) |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | /// Gets all types matching the given namespace and name. |
| 183 | pub fn with_full_name(&self, namespace: &str, name: &str) -> impl Iterator<Item = Type> + '_ { |
| 184 | self.get(namespace) |
| 185 | .and_then(|types| types.get(name)) |
| 186 | .into_iter() |
| 187 | .flatten() |
| 188 | .cloned() |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | enum Category { |
| 193 | Interface, |
| 194 | Class, |
| 195 | Enum, |
| 196 | Struct, |
| 197 | Delegate, |
| 198 | Attribute, |
| 199 | } |
| 200 | |
| 201 | impl Category { |
| 202 | fn new(def: TypeDef) -> Self { |
| 203 | if let Some(extends: TypeName) = def.extends() { |
| 204 | if extends.namespace() == "System" { |
| 205 | match extends.name() { |
| 206 | "Enum" => Self::Enum, |
| 207 | "MulticastDelegate" => Self::Delegate, |
| 208 | "ValueType" => Self::Struct, |
| 209 | "Attribute" => Self::Attribute, |
| 210 | _ => Self::Class, |
| 211 | } |
| 212 | } else { |
| 213 | Self::Class |
| 214 | } |
| 215 | } else { |
| 216 | Self::Interface |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | |