1use super::*;
2mod into_stream;
3
4mod rec;
5
6mod blobs;
7use blobs::*;
8
9mod strings;
10use strings::*;
11
12mod helpers;
13use helpers::*;
14
15#[derive(Default)]
17pub struct File {
18 strings: Strings,
19 blobs: Blobs,
20 records: rec::Records,
21 reference: Option<reader::Index>,
22
23 TypeRef: HashMap<String, HashMap<String, TypeRef>>,
24 TypeSpec: HashMap<BlobId, TypeSpec>,
25 AssemblyRef: HashMap<String, AssemblyRef>,
26 ModuleRef: HashMap<String, ModuleRef>,
27 MemberRef: HashMap<rec::MemberRef, MemberRef>,
28
29 Constant: BTreeMap<HasConstant, rec::Constant>,
31 Attribute: BTreeMap<HasAttribute, Vec<rec::Attribute>>,
32 GenericParam: BTreeMap<TypeOrMethodDef, Vec<rec::GenericParam>>,
33}
34
35impl File {
36 pub fn new(name: &str) -> Self {
37 let mut file = Self::default();
38
39 file.records.Assembly.push(rec::Assembly {
40 Name: file.strings.insert(name),
41 HashAlgId: 0x00008004,
42 MajorVersion: 0xFF,
43 MinorVersion: 0xFF,
44 BuildNumber: 0xFF,
45 RevisionNumber: 0xFF,
46 Flags: AssemblyFlags::WindowsRuntime,
47 ..Default::default()
48 });
49
50 file.records.Module.push(rec::Module {
51 Name: file.strings.insert(name),
52 Mvid: 1,
53 ..Default::default()
54 });
55
56 file.AssemblyRef("System");
58
59 file.TypeDef("", "<Module>", TypeDefOrRef::default(), TypeAttributes(0));
60
61 file
62 }
63
64 pub fn set_reference(&mut self, reference: reader::Index) {
66 self.reference = Some(reference);
67 }
68
69 pub fn reference(&self) -> Option<&reader::Index> {
70 self.reference.as_ref()
71 }
72
73 fn ModuleRef(&mut self, name: &str) -> ModuleRef {
74 if let Some(pos) = self.ModuleRef.get(name) {
75 return *pos;
76 }
77
78 let pos = ModuleRef(self.records.ModuleRef.push_pos(rec::ModuleRef {
79 Name: self.strings.insert(name),
80 }));
81
82 self.ModuleRef.insert(name.to_string(), pos);
83 pos
84 }
85
86 pub fn ImplMap(
87 &mut self,
88 method: MethodDef,
89 flags: PInvokeAttributes,
90 import_name: &str,
91 import_scope: &str,
92 ) {
93 let scope = self.ModuleRef(import_scope);
94
95 self.records.ImplMap.push(rec::ImplMap {
96 MappingFlags: flags,
97 MemberForwarded: MemberForwarded::MethodDef(method),
98 ImportName: self.strings.insert(import_name),
99 ImportScope: scope,
100 });
101 }
102
103 fn AssemblyRef(&mut self, assembly_name: &str) -> AssemblyRef {
104 if let Some(pos) = self.AssemblyRef.get(assembly_name) {
105 return *pos;
106 }
107
108 let pos = AssemblyRef(if assembly_name == "System" {
109 self.records.AssemblyRef.push_pos(rec::AssemblyRef {
110 Name: self.strings.insert("mscorlib"),
111 MajorVersion: 4,
112 PublicKeyOrToken: self
113 .blobs
114 .insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]),
115 ..Default::default()
116 })
117 } else {
118 self.records.AssemblyRef.push_pos(rec::AssemblyRef {
119 Name: self.strings.insert(assembly_name),
120 MajorVersion: 0xFF,
121 MinorVersion: 0xFF,
122 BuildNumber: 0xFF,
123 RevisionNumber: 0xFF,
124 Flags: AssemblyFlags::WindowsRuntime,
125 ..Default::default()
126 })
127 });
128
129 self.AssemblyRef.insert(assembly_name.to_string(), pos);
130 pos
131 }
132
133 pub fn TypeDef(
134 &mut self,
135 namespace: &str,
136 name: &str,
137 extends: TypeDefOrRef,
138 flags: TypeAttributes,
139 ) -> TypeDef {
140 TypeDef(self.records.TypeDef.push_pos(rec::TypeDef {
141 TypeName: self.strings.insert(name),
142 TypeNamespace: self.strings.insert(namespace),
143 Flags: flags,
144 Extends: extends,
145 FieldList: self.records.Field.len() as u32,
146 MethodList: self.records.MethodDef.len() as u32,
147 }))
148 }
149
150 pub fn TypeRef(&mut self, namespace: &str, name: &str) -> TypeRef {
151 if let Some(key) = self.TypeRef.get(namespace)
152 && let Some(pos) = key.get(name)
153 {
154 return *pos;
155 }
156
157 let pos = if let Some((parent, leaf)) = name.rsplit_once('/') {
158 let enclosing = self.TypeRef(namespace, parent);
159 TypeRef(self.records.TypeRef.push_pos(rec::TypeRef {
160 TypeName: self.strings.insert(leaf),
161 TypeNamespace: self.strings.insert(""),
162 ResolutionScope: ResolutionScope::TypeRef(enclosing),
163 }))
164 } else {
165 let assembly_name = self
166 .reference
167 .as_ref()
168 .and_then(|r| r.assembly_name(namespace, name))
169 .map(str::to_string);
170
171 let scope = if let Some(assembly_name) = assembly_name {
172 ResolutionScope::AssemblyRef(self.AssemblyRef(&assembly_name))
173 } else if namespace == "System" {
174 ResolutionScope::AssemblyRef(self.AssemblyRef("System"))
175 } else {
176 ResolutionScope::Module(Module(0))
177 };
178
179 TypeRef(self.records.TypeRef.push_pos(rec::TypeRef {
180 TypeName: self.strings.insert(name),
181 TypeNamespace: self.strings.insert(namespace),
182 ResolutionScope: scope,
183 }))
184 };
185
186 self.TypeRef
187 .entry(namespace.to_string())
188 .or_default()
189 .insert(name.to_string(), pos);
190
191 pos
192 }
193
194 pub fn TypeSpec(&mut self, namespace: &str, name: &str, generics: &[Type]) -> TypeSpec {
195 debug_assert!(!generics.is_empty());
196 let base = name.split_once('`').map_or(name, |(base, _)| base);
198 let name = format!("{base}`{}", generics.len());
199 let type_ref = self.TypeRef(namespace, &name);
200
201 let mut buffer = vec![];
202 buffer.push(ELEMENT_TYPE_GENERICINST);
203 buffer.push(ELEMENT_TYPE_CLASS);
204 buffer.write_compressed(TypeDefOrRef::TypeRef(type_ref).encode() as usize);
205 buffer.write_compressed(generics.len());
206
207 for ty in generics {
208 self.Type(ty, &mut buffer);
209 }
210
211 let signature = self.blobs.insert(&buffer);
212
213 if let Some(pos) = self.TypeSpec.get(&signature) {
214 return *pos;
215 }
216
217 let pos = TypeSpec(self.records.TypeSpec.push_pos(rec::TypeSpec {
218 Signature: signature,
219 }));
220 self.TypeSpec.insert(signature, pos);
221 pos
222 }
223
224 pub fn Field(&mut self, name: &str, ty: &Type, flags: FieldAttributes) -> Field {
225 let signature = self.FieldSig(ty);
226
227 Field(self.records.Field.push_pos(rec::Field {
228 Name: self.strings.insert(name),
229 Flags: flags,
230 Signature: signature,
231 }))
232 }
233
234 pub fn MethodDef(
235 &mut self,
236 name: &str,
237 signature: &Signature,
238 flags: MethodAttributes,
239 impl_flags: MethodImplAttributes,
240 ) -> MethodDef {
241 let signature = self.MethodDefSig(signature);
242
243 MethodDef(self.records.MethodDef.push_pos(rec::MethodDef {
244 RVA: 0,
245 ImplFlags: impl_flags,
246 Flags: flags,
247 Name: self.strings.insert(name),
248 Signature: signature,
249 ParamList: self.records.Param.len() as u32,
250 }))
251 }
252
253 pub fn MemberRef(
254 &mut self,
255 name: &str,
256 signature: &Signature,
257 parent: MemberRefParent,
258 ) -> MemberRef {
259 let signature = self.MethodDefSig(signature);
260
261 let record = rec::MemberRef {
262 Name: self.strings.insert(name),
263 Signature: signature,
264 Parent: parent,
265 };
266
267 if let Some(pos) = self.MemberRef.get(&record) {
268 return *pos;
269 }
270
271 let pos = MemberRef(self.records.MemberRef.push_pos(record));
272 self.MemberRef.insert(record, pos);
273 pos
274 }
275
276 pub fn Param(&mut self, name: &str, sequence: u16, flags: ParamAttributes) -> Param {
278 Param(self.records.Param.push_pos(rec::Param {
279 Flags: flags,
280 Sequence: sequence,
281 Name: self.strings.insert(name),
282 }))
283 }
284
285 pub fn Property(&mut self, name: &str, ty: &Type) -> Property {
287 let signature = self.PropertySig(ty);
288
289 Property(self.records.Property.push_pos(rec::Property {
290 Flags: 0,
291 Name: self.strings.insert(name),
292 Type: signature,
293 }))
294 }
295
296 pub fn PropertyMap(&mut self, parent: TypeDef, property_list: Property) -> PropertyMap {
298 PropertyMap(self.records.PropertyMap.push_pos(rec::PropertyMap {
299 Parent: parent,
300 PropertyList: property_list,
301 }))
302 }
303
304 pub fn Event(&mut self, name: &str, ty: &Type) -> Event {
307 let Type::ClassName(ty) = ty else {
308 panic!("invalid event type");
309 };
310 let event_type = TypeDefOrRef::TypeRef(self.TypeRef(&ty.namespace, &ty.name));
311
312 Event(self.records.Event.push_pos(rec::Event {
313 Flags: 0,
314 Name: self.strings.insert(name),
315 EventType: event_type,
316 }))
317 }
318
319 pub fn EventMap(&mut self, parent: TypeDef, event_list: Event) -> EventMap {
321 EventMap(self.records.EventMap.push_pos(rec::EventMap {
322 Parent: parent,
323 EventList: event_list,
324 }))
325 }
326
327 pub fn MethodSemantics(
329 &mut self,
330 semantics: u16,
331 method: MethodDef,
332 association: HasSemantics,
333 ) -> MethodSemantics {
334 MethodSemantics(self.records.MethodSemantics.push_pos(rec::MethodSemantics {
335 Semantics: semantics,
336 Method: method,
337 Association: association,
338 }))
339 }
340
341 pub fn Attribute(
343 &mut self,
344 parent: HasAttribute,
345 ty: AttributeType,
346 value: &[(String, Value)],
347 ) {
348 let value = self.AttributeValue(value);
349
350 self.Attribute
351 .entry(parent)
352 .or_default()
353 .push(rec::Attribute {
354 Parent: parent,
355 Type: ty,
356 Value: value,
357 });
358 }
359
360 pub fn Constant(&mut self, parent: HasConstant, value: &Value) {
361 let ty = value.ty().code();
362 let value = self.ConstantValue(value);
363
364 self.Constant.insert(
365 parent,
366 rec::Constant {
367 Parent: parent,
368 Type: ty,
369 Value: value,
370 },
371 );
372 }
373
374 pub fn GenericParam(
375 &mut self,
376 name: &str,
377 owner: TypeOrMethodDef,
378 number: u16,
379 flags: GenericParamAttributes,
380 ) {
381 self.GenericParam
382 .entry(owner)
383 .or_default()
384 .push(rec::GenericParam {
385 Name: self.strings.insert(name),
386 Number: number,
387 Owner: owner,
388 Flags: flags,
389 });
390 }
391
392 pub fn ClassLayout(&mut self, parent: TypeDef, packing_size: u16, class_size: u32) {
393 self.records.ClassLayout.push(rec::ClassLayout {
394 PackingSize: packing_size,
395 ClassSize: class_size,
396 Parent: parent.0,
397 });
398 }
399
400 pub fn FieldLayout(&mut self, field: Field, offset: u32) {
401 self.records.FieldLayout.push(rec::FieldLayout {
402 Offset: offset,
403 Field: field.0,
404 });
405 }
406
407 pub fn NestedClass(&mut self, inner: TypeDef, outer: TypeDef) {
408 debug_assert!(inner.0 > outer.0);
409
410 self.records.NestedClass.push(rec::NestedClass {
411 NestedClass: inner.0,
412 EnclosingClass: outer.0,
413 });
414 }
415
416 pub fn InterfaceImpl(&mut self, class: TypeDef, interface: &Type) -> InterfaceImpl {
417 let Type::ClassName(interface) = interface else {
418 panic!("invalid interface type");
419 };
420
421 let interface = if interface.generics.is_empty() {
422 TypeDefOrRef::TypeRef(self.TypeRef(&interface.namespace, &interface.name))
423 } else {
424 TypeDefOrRef::TypeSpec(self.TypeSpec(
425 &interface.namespace,
426 &interface.name,
427 &interface.generics,
428 ))
429 };
430
431 InterfaceImpl(self.records.InterfaceImpl.push_pos(rec::InterfaceImpl {
432 Class: class,
433 Interface: interface,
434 }))
435 }
436
437 fn Type(&mut self, ty: &Type, buffer: &mut Vec<u8>) {
439 match ty {
440 Type::Void => buffer.push(ELEMENT_TYPE_VOID),
441 Type::Bool => buffer.push(ELEMENT_TYPE_BOOLEAN),
442 Type::Char => buffer.push(ELEMENT_TYPE_CHAR),
443 Type::I8 => buffer.push(ELEMENT_TYPE_I1),
444 Type::U8 => buffer.push(ELEMENT_TYPE_U1),
445 Type::I16 => buffer.push(ELEMENT_TYPE_I2),
446 Type::U16 => buffer.push(ELEMENT_TYPE_U2),
447 Type::I32 => buffer.push(ELEMENT_TYPE_I4),
448 Type::U32 => buffer.push(ELEMENT_TYPE_U4),
449 Type::I64 => buffer.push(ELEMENT_TYPE_I8),
450 Type::U64 => buffer.push(ELEMENT_TYPE_U8),
451 Type::F32 => buffer.push(ELEMENT_TYPE_R4),
452 Type::F64 => buffer.push(ELEMENT_TYPE_R8),
453 Type::ISize => buffer.push(ELEMENT_TYPE_I),
454 Type::USize => buffer.push(ELEMENT_TYPE_U),
455 Type::String => buffer.push(ELEMENT_TYPE_STRING),
456 Type::Object => buffer.push(ELEMENT_TYPE_OBJECT),
457
458 Type::Array(ty) => {
459 buffer.push(ELEMENT_TYPE_SZARRAY);
460 self.Type(ty, buffer);
461 }
462
463 Type::RefMut(ty) => {
464 buffer.push(ELEMENT_TYPE_BYREF);
465 self.Type(ty, buffer);
466 }
467
468 Type::RefConst(ty) => {
469 buffer.write_compressed(ELEMENT_TYPE_CMOD_REQD as usize);
470 let pos = self.TypeRef("System.Runtime.CompilerServices", "IsConst");
471 buffer.write_compressed(TypeDefOrRef::TypeRef(pos).encode() as usize);
472 buffer.push(ELEMENT_TYPE_BYREF);
473 self.Type(ty, buffer);
474 }
475
476 Type::PtrMut(ty, pointers) => {
477 for _ in 0..*pointers {
478 buffer.write_compressed(ELEMENT_TYPE_PTR as usize);
479 }
480
481 self.Type(ty, buffer);
482 }
483
484 Type::PtrConst(ty, pointers) => {
485 buffer.write_compressed(ELEMENT_TYPE_CMOD_REQD as usize);
486 let pos = self.TypeRef("System.Runtime.CompilerServices", "IsConst");
487 buffer.write_compressed(TypeDefOrRef::TypeRef(pos).encode() as usize);
488
489 for _ in 0..*pointers {
490 buffer.write_compressed(ELEMENT_TYPE_PTR as usize);
491 }
492
493 self.Type(ty, buffer);
494 }
495
496 Type::ArrayFixed(ty, len) => {
497 buffer.push(ELEMENT_TYPE_ARRAY);
499 self.Type(ty, buffer);
500 buffer.write_compressed(1); buffer.write_compressed(1); buffer.write_compressed(*len); buffer.write_compressed(0); }
505
506 Type::Generic(_, number) => {
507 buffer.push(ELEMENT_TYPE_VAR);
508 buffer.write_compressed((*number).into());
509 }
510
511 Type::ClassName(ty) => {
512 self.TypeName(false, &ty.namespace, &ty.name, &ty.generics, buffer);
513 }
514 Type::ValueName(ty) => {
515 self.TypeName(true, &ty.namespace, &ty.name, &ty.generics, buffer);
516 }
517 }
518 }
519
520 fn TypeName(
521 &mut self,
522 is_value_type: bool,
523 namespace: &str,
524 name: &str,
525 generics: &[Type],
526 buffer: &mut Vec<u8>,
527 ) {
528 let pos = if !generics.is_empty() {
529 buffer.push(ELEMENT_TYPE_GENERICINST);
530 let base = name.split_once('`').map_or(name, |(base, _)| base);
532 let name = format!("{base}`{}", generics.len());
533 self.TypeRef(namespace, &name)
534 } else {
535 self.TypeRef(namespace, name)
536 };
537
538 buffer.push(if is_value_type {
539 ELEMENT_TYPE_VALUETYPE
540 } else {
541 ELEMENT_TYPE_CLASS
542 });
543 buffer.write_compressed(TypeDefOrRef::TypeRef(pos).encode() as usize);
544
545 if !generics.is_empty() {
546 buffer.write_compressed(generics.len());
547
548 for ty in generics {
549 self.Type(ty, buffer);
550 }
551 }
552 }
553
554 fn FieldSig(&mut self, ty: &Type) -> BlobId {
557 let mut buffer = vec![0x6]; self.Type(ty, &mut buffer);
559 self.blobs.insert(&buffer)
560 }
561
562 fn PropertySig(&mut self, ty: &Type) -> BlobId {
563 let mut buffer = vec![0x28]; buffer.write_compressed(0); self.Type(ty, &mut buffer);
566 self.blobs.insert(&buffer)
567 }
568
569 fn MethodDefSig(&mut self, signature: &Signature) -> BlobId {
571 let mut buffer = vec![signature.flags.0];
572 buffer.write_compressed(signature.types.len());
573 self.Type(&signature.return_type, &mut buffer);
574
575 for ty in &signature.types {
576 self.Type(ty, &mut buffer);
577 }
578
579 self.blobs.insert(&buffer)
580 }
581
582 fn ConstantValue(&mut self, value: &Value) -> BlobId {
583 let mut buffer = vec![];
584 buffer.write_value(value);
585 self.blobs.insert(&buffer)
586 }
587
588 fn AttributeValue(&mut self, values: &[(String, Value)]) -> BlobId {
589 let mut buffer = vec![];
590 buffer.write_u16(1); let mut count = 0;
593
594 for (name, value) in values {
595 if name.is_empty() {
596 count += 1;
597 buffer.write_value(value);
598 } else {
599 break;
600 }
601 }
602
603 buffer.write_u16((values.len() - count).try_into().unwrap());
604
605 for (name, value) in &values[count..] {
606 buffer.push(0x53); if let Value::EnumValue(tn, _) = value {
609 buffer.push(0x55);
612 let enum_name = if tn.namespace.is_empty() {
613 tn.name.clone()
614 } else {
615 format!("{}.{}", tn.namespace, tn.name)
616 };
617 buffer.write_compressed(enum_name.len());
618 buffer.extend_from_slice(enum_name.as_bytes());
619 } else {
620 buffer.push(value.ty().code());
621 }
622
623 buffer.write_compressed(name.len());
624 buffer.extend_from_slice(name.as_bytes());
625 buffer.write_value(value);
626 }
627
628 self.blobs.insert(&buffer)
629 }
630}