1use super::*;
2
3macro_rules! tables {
4 ($(($name:ident, $table:literal))+) => {
5 $(
6 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
7 pub struct $name(pub Row);
8 impl AsRow for $name {
9 const TABLE: usize = $table;
10 fn to_row(&self) -> Row {
11 self.0
12 }
13 fn from_row(row: Row) -> Self {
14 $name(row)
15 }
16 }
17 )*
18 };
19}
20
21tables! {
22 (AssemblyRef, 15)
23 (Attribute, 1)
24 (ClassLayout, 16)
25 (Constant, 0)
26 (Field, 2)
27 (GenericParam, 3)
28 (ImplMap, 11)
29 (InterfaceImpl, 4)
30 (MemberRef, 5)
31 (MethodDef, 6)
32 (Module, 14)
33 (ModuleRef, 12)
34 (NestedClass, 13)
35 (Param, 7)
36 (TypeDef, 8)
37 (TypeRef, 9)
38 (TypeSpec, 10)
39}
40
41impl Attribute {
42 pub fn parent(&self) -> HasAttribute {
43 self.decode(0)
44 }
45
46 pub fn ty(&self) -> AttributeType {
47 self.decode(1)
48 }
49
50 pub fn name(&self) -> &'static str {
51 let AttributeType::MemberRef(ctor) = self.ty();
52 let MemberRefParent::TypeRef(ty) = ctor.parent();
53 ty.name()
54 }
55
56 pub fn type_name(&self) -> TypeName {
57 let AttributeType::MemberRef(ctor) = self.ty();
58 let MemberRefParent::TypeRef(ty) = ctor.parent();
59 ty.type_name()
60 }
61
62 pub fn args(&self) -> Vec<(&'static str, Value)> {
63 let AttributeType::MemberRef(member) = self.ty();
64 let mut sig = member.blob(2);
65 let mut values = self.blob(2);
66 let _prolog = values.read_u16();
67 let _this_and_gen_param_count = sig.read_usize();
68 let fixed_arg_count = sig.read_usize();
69 let _ret_type = sig.read_usize();
70 let mut args = Vec::with_capacity(fixed_arg_count);
71 let reader = self.reader();
72
73 for _ in 0..fixed_arg_count {
74 let arg = match reader.type_from_blob(&mut sig, None, &[]) {
75 Type::Bool => Value::Bool(values.read_bool()),
76 Type::I8 => Value::I8(values.read_i8()),
77 Type::U8 => Value::U8(values.read_u8()),
78 Type::I16 => Value::I16(values.read_i16()),
79 Type::U16 => Value::U16(values.read_u16()),
80 Type::I32 => Value::I32(values.read_i32()),
81 Type::U32 => Value::U32(values.read_u32()),
82 Type::I64 => Value::I64(values.read_i64()),
83 Type::U64 => Value::U64(values.read_u64()),
84 Type::String => Value::String(values.read_str().to_string()),
85 Type::Type => Value::TypeName(TypeName::parse(values.read_str())),
86 Type::TypeDef(def, _) => Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type()))),
87 rest => unimplemented!("{rest:?}"),
88 };
89
90 args.push(("", arg));
91 }
92
93 let named_arg_count = values.read_u16();
94 args.reserve(named_arg_count as usize);
95
96 for _ in 0..named_arg_count {
97 let _id = values.read_u8();
98 let arg_type = values.read_u8();
99 let mut name = values.read_str();
100 let arg = match arg_type {
101 ELEMENT_TYPE_BOOLEAN => Value::Bool(values.read_bool()),
102 ELEMENT_TYPE_I2 => Value::I16(values.read_i16()),
103 ELEMENT_TYPE_I4 => Value::I32(values.read_i32()),
104 ELEMENT_TYPE_U4 => Value::U32(values.read_u32()),
105 ELEMENT_TYPE_STRING => Value::String(values.read_str().to_string()),
106 0x50 => Value::TypeName(TypeName::parse(values.read_str())),
107 0x55 => {
108 let type_name = TypeName::parse(name);
109 let def = reader.get_type_def(type_name.namespace, type_name.name).next().expect("Type not found");
110 name = values.read_str();
111 Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type())))
112 }
113 rest => unimplemented!("{rest:?}"),
114 };
115 args.push((name, arg));
116 }
117
118 debug_assert_eq!(sig.slice.len(), 0);
119 debug_assert_eq!(values.slice.len(), 0);
120
121 args
122 }
123}
124
125impl ClassLayout {
126 pub fn packing_size(&self) -> usize {
127 self.usize(column:0)
128 }
129}
130
131impl Constant {
132 pub fn ty(&self) -> Type {
133 Type::from_code(self.usize(0)).expect(msg:"Constant type not found")
134 }
135
136 pub fn value(&self) -> Value {
137 let mut blob: Blob = self.blob(column:2);
138
139 match self.ty() {
140 Type::I8 => Value::I8(blob.read_i8()),
141 Type::U8 => Value::U8(blob.read_u8()),
142 Type::I16 => Value::I16(blob.read_i16()),
143 Type::U16 => Value::U16(blob.read_u16()),
144 Type::I32 => Value::I32(blob.read_i32()),
145 Type::U32 => Value::U32(blob.read_u32()),
146 Type::I64 => Value::I64(blob.read_i64()),
147 Type::U64 => Value::U64(blob.read_u64()),
148 Type::F32 => Value::F32(blob.read_f32()),
149 Type::F64 => Value::F64(blob.read_f64()),
150 Type::String => Value::String(blob.read_string()),
151 rest: Type => unimplemented!("{rest:?}"),
152 }
153 }
154}
155
156impl Field {
157 pub fn flags(&self) -> FieldAttributes {
158 FieldAttributes(self.usize(0) as u16)
159 }
160
161 pub fn name(&self) -> &'static str {
162 self.str(1)
163 }
164
165 pub fn constant(&self) -> Option<Constant> {
166 self.equal_range(1, HasConstant::Field(*self).encode()).next()
167 }
168
169 // TODO: enclosing craziness is only needed for nested structs - get rid of those in riddle and this goes away.
170 pub fn ty(&self, enclosing: Option<TypeDef>) -> Type {
171 let mut blob = self.blob(2);
172 blob.read_usize();
173 blob.read_modifiers();
174 let def = self.reader().type_from_blob(&mut blob, enclosing, &[]);
175
176 if self.has_attribute("ConstAttribute") {
177 def.to_const_type().to_const_ptr()
178 } else {
179 def
180 }
181 }
182}
183
184impl GenericParam {
185 pub fn number(&self) -> u16 {
186 self.usize(column:0) as u16
187 }
188
189 pub fn name(&self) -> &'static str {
190 self.str(column:3)
191 }
192}
193
194impl ImplMap {
195 pub fn flags(&self) -> PInvokeAttributes {
196 PInvokeAttributes(self.usize(column:0))
197 }
198
199 pub fn scope(&self) -> ModuleRef {
200 ModuleRef(self.row(column:3))
201 }
202
203 pub fn import_name(&self) -> &'static str {
204 self.str(column:2)
205 }
206}
207
208impl InterfaceImpl {
209 pub fn ty(&self, generics: &[Type]) -> Type {
210 self.reader().type_from_ref(self.decode(1), enclosing:None, generics)
211 }
212}
213
214impl MemberRef {
215 pub fn parent(&self) -> MemberRefParent {
216 self.decode(column:0)
217 }
218
219 pub fn name(&self) -> &'static str {
220 self.str(column:1)
221 }
222}
223
224impl MethodDef {
225 pub fn impl_flags(&self) -> MethodImplAttributes {
226 MethodImplAttributes(self.usize(1) as u16)
227 }
228
229 pub fn flags(&self) -> MethodAttributes {
230 MethodAttributes(self.usize(2) as u16)
231 }
232
233 pub fn name(&self) -> &'static str {
234 self.str(3)
235 }
236
237 pub fn params(&self) -> RowIterator<Param> {
238 self.list(5)
239 }
240
241 pub fn impl_map(&self) -> Option<ImplMap> {
242 self.equal_range(1, MemberForwarded::MethodDef(*self).encode()).next()
243 }
244
245 pub fn module_name(&self) -> String {
246 // TODO: riddle should always lower case the module name to avoid allocating here
247 let Some(impl_map) = self.impl_map() else {
248 return String::new();
249 };
250
251 impl_map.scope().name().to_lowercase()
252 }
253
254 pub fn signature(&self, generics: &[Type]) -> MethodDefSig {
255 let reader = self.reader();
256 let mut blob = self.blob(4);
257 let call_flags = MethodCallAttributes(blob.read_usize() as u8);
258 let params = blob.read_usize();
259 let return_type = reader.type_from_blob(&mut blob, None, generics);
260
261 MethodDefSig { call_flags, return_type, params: (0..params).map(|_| reader.type_from_blob(&mut blob, None, generics)).collect() }
262 }
263}
264
265impl ModuleRef {
266 pub fn name(&self) -> &'static str {
267 self.str(column:0)
268 }
269}
270
271impl NestedClass {
272 pub fn inner(&self) -> TypeDef {
273 TypeDef(self.row(column:0))
274 }
275
276 pub fn outer(&self) -> TypeDef {
277 TypeDef(self.row(column:1))
278 }
279}
280
281impl Param {
282 pub fn flags(&self) -> ParamAttributes {
283 ParamAttributes(self.usize(column:0) as u16)
284 }
285
286 pub fn sequence(&self) -> u16 {
287 self.usize(column:1) as u16
288 }
289
290 pub fn name(&self) -> &'static str {
291 self.str(column:2)
292 }
293}
294
295impl TypeDef {
296 pub fn flags(&self) -> TypeAttributes {
297 TypeAttributes(self.usize(0) as u32)
298 }
299
300 pub fn name(&self) -> &'static str {
301 trim_tick(self.str(1))
302 }
303
304 pub fn namespace(&self) -> &'static str {
305 self.str(2)
306 }
307
308 pub fn type_name(&self) -> TypeName {
309 TypeName::new(self.namespace(), self.name())
310 }
311
312 pub fn extends(&self) -> Option<TypeName> {
313 let extends = self.usize(3);
314
315 if extends == 0 {
316 return None;
317 }
318
319 Some(TypeDefOrRef::decode(self.file(), extends).type_name())
320 }
321
322 pub fn methods(&self) -> RowIterator<MethodDef> {
323 self.list(5)
324 }
325
326 pub fn fields(&self) -> RowIterator<Field> {
327 self.list(4)
328 }
329
330 pub fn generics(&self) -> RowIterator<GenericParam> {
331 self.equal_range(2, TypeOrMethodDef::TypeDef(*self).encode())
332 }
333
334 pub fn interface_impls(&self) -> RowIterator<InterfaceImpl> {
335 self.equal_range(0, self.index() + 1)
336 }
337
338 pub fn enclosing_type(&self) -> Option<TypeDef> {
339 self.equal_range::<NestedClass>(0, self.index() + 1).next().map(|row| TypeDef(row.row(1)))
340 }
341
342 pub fn class_layout(&self) -> Option<ClassLayout> {
343 self.equal_range(2, self.index() + 1).next()
344 }
345
346 pub fn underlying_type(&self) -> Type {
347 let field = self.fields().next().expect("Field not found");
348 if let Some(constant) = field.constant() {
349 constant.ty()
350 } else {
351 field.ty(Some(*self))
352 }
353 }
354
355 pub fn kind(&self) -> TypeKind {
356 match self.extends() {
357 None => TypeKind::Interface,
358 Some(TypeName::Enum) => TypeKind::Enum,
359 Some(TypeName::Delegate) => TypeKind::Delegate,
360 Some(TypeName::Struct) => TypeKind::Struct,
361 Some(_) => TypeKind::Class,
362 }
363 }
364
365 pub fn size(&self) -> usize {
366 match self.kind() {
367 TypeKind::Struct => {
368 if self.flags().contains(TypeAttributes::ExplicitLayout) {
369 self.fields().map(|field| field.ty(Some(*self)).size()).max().unwrap_or(1)
370 } else {
371 let mut sum = 0;
372 for field in self.fields() {
373 let ty = field.ty(Some(*self));
374 let size = ty.size();
375 let align = ty.align();
376 sum = (sum + (align - 1)) & !(align - 1);
377 sum += size;
378 }
379 sum
380 }
381 }
382 TypeKind::Enum => self.underlying_type().size(),
383 _ => 4,
384 }
385 }
386
387 pub fn align(&self) -> usize {
388 match self.kind() {
389 TypeKind::Struct => self.fields().map(|field| field.ty(Some(*self)).align()).max().unwrap_or(1),
390 TypeKind::Enum => self.underlying_type().align(),
391 _ => 4,
392 }
393 }
394}
395
396impl TypeRef {
397 pub fn name(&self) -> &'static str {
398 trim_tick(self.str(column:1))
399 }
400
401 pub fn namespace(&self) -> &'static str {
402 self.str(column:2)
403 }
404
405 pub fn type_name(&self) -> TypeName {
406 TypeName::new(self.namespace(), self.name())
407 }
408
409 pub fn resolution_scope(&self) -> ResolutionScope {
410 self.decode(column:0)
411 }
412}
413
414fn trim_tick(name: &str) -> &str {
415 if name.as_bytes().iter().rev().nth(1) == Some(&b'`') {
416 &name[..name.len() - 2]
417 } else {
418 name
419 }
420}
421