1#![allow(non_snake_case)]
2
3use super::Write;
4use super::*;
5use metadata::*;
6
7#[derive(Default)]
8pub struct Tables {
9 // TODO: use BTreeSet for tables that have a primary key, unless they are naturally sorted.
10 pub Assembly: Vec<Assembly>,
11 pub AssemblyRef: Vec<AssemblyRef>,
12 pub ClassLayout: Vec<ClassLayout>,
13 pub Constant: Vec<Constant>,
14 pub CustomAttribute: Vec<CustomAttribute>,
15 pub Field: Vec<Field>,
16 pub GenericParam: Vec<GenericParam>,
17 pub ImplMap: Vec<ImplMap>,
18 pub InterfaceImpl: Vec<InterfaceImpl>,
19 pub MemberRef: Vec<MemberRef>,
20 pub MethodDef: Vec<MethodDef>,
21 pub Module: Vec<Module>,
22 pub ModuleRef: Vec<ModuleRef>,
23 pub NestedClass: Vec<NestedClass>,
24 pub Param: Vec<Param>,
25 pub Property: Vec<Property>,
26 pub TypeDef: Vec<TypeDef>,
27 pub TypeRef: Vec<TypeRef>,
28 pub TypeSpec: Vec<TypeSpec>,
29}
30
31#[derive(Default)]
32pub struct Assembly {
33 pub HashAlgId: u32,
34 pub MajorVersion: u16,
35 pub MinorVersion: u16,
36 pub BuildNumber: u16,
37 pub RevisionNumber: u16,
38 pub Flags: u32,
39 pub PublicKey: u32,
40 pub Name: u32,
41 pub Culture: u32,
42}
43
44#[derive(Default)]
45pub struct AssemblyRef {
46 pub MajorVersion: u16,
47 pub MinorVersion: u16,
48 pub BuildNumber: u16,
49 pub RevisionNumber: u16,
50 pub Flags: u32,
51 pub PublicKeyOrToken: u32,
52 pub Name: u32,
53 pub Culture: u32,
54 pub HashValue: u32,
55}
56
57#[derive(Default)]
58pub struct ClassLayout {
59 pub PackingSize: u16,
60 pub ClassSize: u32,
61 pub Parent: u32,
62}
63
64#[derive(Default)]
65pub struct Constant {
66 pub Type: u16,
67 pub Parent: u32,
68 pub Value: u32,
69}
70
71#[derive(Default)]
72pub struct CustomAttribute {
73 pub Parent: u32,
74 pub Type: u32,
75 pub Value: u32,
76}
77
78#[derive(Default)]
79pub struct Field {
80 pub Flags: u16,
81 pub Name: u32,
82 pub Signature: u32,
83}
84
85#[derive(Default)]
86pub struct GenericParam {
87 pub Number: u16,
88 pub Flags: u16,
89 pub Owner: u32,
90 pub Name: u32,
91}
92
93#[derive(Default)]
94pub struct ImplMap {
95 pub MappingFlags: u16,
96 pub MemberForwarded: u32,
97 pub ImportName: u32,
98 pub ImportScope: u32,
99}
100
101#[derive(Default)]
102pub struct InterfaceImpl {
103 pub Class: u32,
104 pub Interface: u32,
105}
106
107#[derive(Default)]
108pub struct MemberRef {
109 pub Class: u32,
110 pub Name: u32,
111 pub Signature: u32,
112}
113
114#[derive(Default)]
115pub struct MethodDef {
116 pub RVA: u32,
117 pub ImplFlags: u16,
118 pub Flags: u16,
119 pub Name: u32,
120 pub Signature: u32,
121 pub ParamList: u32,
122}
123
124#[derive(Default)]
125pub struct Module {
126 pub Generation: u16,
127 pub Name: u32,
128 pub Mvid: u32,
129 pub EncId: u32,
130 pub EncBaseId: u32,
131}
132
133#[derive(Default)]
134pub struct ModuleRef {
135 pub Name: u32,
136}
137
138#[derive(Default)]
139pub struct NestedClass {
140 pub NestedClass: u32,
141 pub EnclosingClass: u32,
142}
143
144#[derive(Default)]
145pub struct Param {
146 pub Flags: u16,
147 pub Sequence: u16,
148 pub Name: u32,
149}
150
151#[derive(Default)]
152pub struct Property {
153 pub Flags: u16,
154 pub Name: u32,
155 pub Type: u32,
156}
157
158#[derive(Default)]
159pub struct TypeDef {
160 pub Flags: u32,
161 pub TypeName: u32,
162 pub TypeNamespace: u32,
163 pub Extends: u32,
164 pub FieldList: u32,
165 pub MethodList: u32,
166}
167
168#[derive(Default)]
169pub struct TypeRef {
170 pub ResolutionScope: u32,
171 pub TypeName: u32,
172 pub TypeNamespace: u32,
173}
174
175#[derive(Default)]
176pub struct TypeSpec {
177 pub Signature: u32,
178}
179
180impl Tables {
181 pub fn into_stream(self) -> Vec<u8> {
182 if [self.AssemblyRef.len(), self.ClassLayout.len(), self.Constant.len(), self.CustomAttribute.len(), self.Field.len(), self.GenericParam.len(), self.ImplMap.len(), self.InterfaceImpl.len(), self.MemberRef.len(), self.MethodDef.len(), self.Module.len(), self.ModuleRef.len(), self.NestedClass.len(), self.Param.len(), self.Property.len(), self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()].iter().any(|len| *len > u32::MAX as usize) {
183 panic!("metadata table too large");
184 }
185
186 let resolution_scope = coded_index_size(&[self.Module.len(), self.ModuleRef.len(), self.AssemblyRef.len(), self.TypeRef.len()]);
187
188 let type_def_or_ref = coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]);
189
190 let has_constant = coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]);
191
192 let type_or_method_def = coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]);
193
194 let valid_tables: u64 = 1 << 0 | // Module
195 1 << 0x01 | // TypeRef
196 1 << 0x02 | // TypeDef
197 1 << 0x04 | // Field
198 1 << 0x06 | // MethodDef
199 1 << 0x08 | // Param
200 1 << 0x09 | // InterfaceImpl
201 1 << 0x0A | // MemberRef
202 1 << 0x0B | // Constant
203 1 << 0x0C | // CustomAttribute
204 1 << 0x0F | // ClassLayout
205 1 << 0x17 | // Property
206 1 << 0x1A | // ModuleRef
207 1 << 0x1B | // TypeSpec
208 1 << 0x1C | // ImplMap
209 1 << 0x20 | // Assembly
210 1 << 0x23 | // AssemblyRef
211 1 << 0x29 | // NestedClass
212 1 << 0x2A; // GenericParam
213
214 // The table stream header...
215
216 let mut buffer = Vec::new();
217 buffer.write_u32(0); // Reserved
218 buffer.write_u8(2); // MajorVersion
219 buffer.write_u8(0); // MinorVersion
220 buffer.write_u8(0b111); // HeapSizes
221 buffer.write_u8(0); // Reserved
222 buffer.write_u64(valid_tables);
223 buffer.write_u64(0); // Sorted
224
225 // Followed by the length of each of the valid tables...
226
227 buffer.write_u32(self.Module.len() as u32);
228 buffer.write_u32(self.TypeRef.len() as u32);
229 buffer.write_u32(self.TypeDef.len() as u32);
230 buffer.write_u32(self.Field.len() as u32);
231 buffer.write_u32(self.MethodDef.len() as u32);
232 buffer.write_u32(self.Param.len() as u32);
233 buffer.write_u32(self.InterfaceImpl.len() as u32);
234 buffer.write_u32(self.MemberRef.len() as u32);
235 buffer.write_u32(self.Constant.len() as u32);
236 buffer.write_u32(self.CustomAttribute.len() as u32);
237 buffer.write_u32(self.ClassLayout.len() as u32);
238 buffer.write_u32(self.Property.len() as u32);
239 buffer.write_u32(self.ModuleRef.len() as u32);
240 buffer.write_u32(self.TypeSpec.len() as u32);
241 buffer.write_u32(self.ImplMap.len() as u32);
242 buffer.write_u32(self.Assembly.len() as u32);
243 buffer.write_u32(self.AssemblyRef.len() as u32);
244 buffer.write_u32(self.NestedClass.len() as u32);
245 buffer.write_u32(self.GenericParam.len() as u32);
246
247 // Followed by each table's rows...
248
249 for x in self.Module {
250 buffer.write_u16(x.Generation);
251 buffer.write_u32(x.Name);
252 buffer.write_u32(x.Mvid);
253 buffer.write_u32(x.EncId);
254 buffer.write_u32(x.EncBaseId);
255 }
256
257 for x in self.TypeRef {
258 buffer.write_code(x.ResolutionScope, resolution_scope);
259 buffer.write_u32(x.TypeName);
260 buffer.write_u32(x.TypeNamespace);
261 }
262
263 for x in &self.TypeDef {
264 buffer.write_u32(x.Flags);
265 buffer.write_u32(x.TypeName);
266 buffer.write_u32(x.TypeNamespace);
267 buffer.write_code(x.Extends, type_def_or_ref);
268 buffer.write_index(x.FieldList, self.Field.len());
269 buffer.write_index(x.MethodList, self.MethodDef.len());
270 }
271
272 for x in self.Field {
273 buffer.write_u16(x.Flags);
274 buffer.write_u32(x.Name);
275 buffer.write_u32(x.Signature);
276 }
277
278 for x in self.MethodDef {
279 buffer.write_u32(x.RVA);
280 buffer.write_u16(x.ImplFlags);
281 buffer.write_u16(x.Flags);
282 buffer.write_u32(x.Name);
283 buffer.write_u32(x.Signature);
284 buffer.write_index(x.ParamList, self.Param.len());
285 }
286
287 for x in self.Param {
288 buffer.write_u16(x.Flags);
289 buffer.write_u16(x.Sequence);
290 buffer.write_u32(x.Name);
291 }
292
293 for x in self.InterfaceImpl {
294 buffer.write_index(x.Class, self.TypeDef.len());
295 buffer.write_code(x.Interface, type_def_or_ref);
296 }
297
298 for x in self.Constant {
299 buffer.write_u16(x.Type);
300 buffer.write_code(x.Parent, has_constant);
301 buffer.write_u32(x.Value);
302 }
303
304 for x in self.TypeSpec {
305 buffer.write_u32(x.Signature);
306 }
307
308 for x in self.Assembly {
309 buffer.write_u32(x.HashAlgId);
310 buffer.write_u16(x.MajorVersion);
311 buffer.write_u16(x.MinorVersion);
312 buffer.write_u16(x.BuildNumber);
313 buffer.write_u16(x.RevisionNumber);
314 buffer.write_u32(x.Flags);
315 buffer.write_u32(x.PublicKey);
316 buffer.write_u32(x.Name);
317 buffer.write_u32(x.Culture);
318 }
319
320 for x in self.AssemblyRef {
321 buffer.write_u16(x.MajorVersion);
322 buffer.write_u16(x.MinorVersion);
323 buffer.write_u16(x.BuildNumber);
324 buffer.write_u16(x.RevisionNumber);
325 buffer.write_u32(x.Flags);
326 buffer.write_u32(x.PublicKeyOrToken);
327 buffer.write_u32(x.Name);
328 buffer.write_u32(x.Culture);
329 buffer.write_u32(x.HashValue);
330 }
331
332 for x in self.GenericParam {
333 buffer.write_u16(x.Number);
334 buffer.write_u16(x.Flags);
335 buffer.write_code(x.Owner, type_or_method_def);
336 buffer.write_u32(x.Name);
337 }
338
339 // TODO: sort GenericParam table prior to writing. This needs to be done for all tables with a primary index. See II.22
340
341 // TODO: do these get naturally sorted by virtue of how they're pushed into "tables" in type def order?
342
343 // Table Primary Key Column
344 // ClassLayout Parent
345 // Constant Parent
346 // CustomAttribute Parent
347 // DeclSecurity Parent
348 // FieldLayout Field
349 // FieldMarshal Parent
350 // FieldRVA Field
351 // GenericParam Owner
352 // GenericParamConstraint Owner
353 // ImplMap MemberForwarded
354 // InterfaceImpl Class
355 // MethodImpl Class
356 // MethodSemantics Association
357 // NestedClass NestedClass
358
359 buffer.into_stream()
360 }
361}
362