1use super::coded_tokens::CodedTokenSizes;
2use super::{tables::*, TableLocation, ValueSize};
3use crate::dotnet::md::calculator::{SizeCalculator, TablePositionCalculator};
4use crate::dotnet::md::streams::Version;
5use crate::dotnet::md::MDStreamFlags;
6use crate::io::ReadData;
7use crate::{error::Result, io::DataReader};
8use bitflags::bitflags;
9
10bitflags! {
11 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12 pub struct TableExistsFlags: u64 {
13 const Module = 1<<0;
14 const TypeRef = 1<<1;
15 const TypeDef = 1<<2;
16 const FieldPtr = 1<<3;
17 const Field = 1<<4;
18 const MethodPtr = 1<<5;
19 const Method = 1<<6;
20 const ParamPtr = 1<<7;
21 const Param = 1<<8;
22 const InterfaceImpl = 1<<9;
23 const MemberRef = 1<<10;
24 const Constant = 1<<11;
25 const CustomAttribute = 1<<12;
26 const FieldMarshal = 1<<13;
27 const DeclSecurity = 1<<14;
28 const ClassLayout = 1<<15;
29 const FieldLayout = 1<<16;
30 const StandAloneSig = 1<<17;
31 const EventMap = 1<<18;
32 const EventPtr = 1<<19;
33 const Event = 1<<20;
34 const PropertyMap = 1<<21;
35 const PropertyPtr = 1<<22;
36 const Property = 1<<23;
37 const MethodSemantics = 1<<24;
38 const MethodImpl = 1<<25;
39 const ModuleRef = 1<<26;
40 const TypeSpec = 1<<27;
41 const ImplMap = 1<<28;
42 const FieldRva = 1<<29;
43 const EncLog = 1<<30;
44 const EncMap = 1<<31;
45 const Assembly = 1<<32;
46 const AssemblyProcessor = 1<<33;
47 const AssemblyOs = 1<<34;
48 const AssemblyRef = 1<<35;
49 const AssemblyRefProcessor = 1<<36;
50 const AssemblyRefOs = 1<<37;
51 const File = 1<<38;
52 const ExportedType = 1<<39;
53 const ManifestResource = 1<<40;
54 const NestedClass = 1<<41;
55 const GenericParam = 1<<42;
56 const MethodSpec = 1<<43;
57 const GenericParamConstraint = 1<<44;
58 const Document = 1<<45;
59 const MethodDebugInformation = 1<<46;
60 const LocalScope = 1<<47;
61 const LocalVariable = 1<<48;
62 const LocalConstant = 1<<49;
63 const ImportScope = 1<<50;
64 const StateMachineMethod = 1<<51;
65 const CustomDebugInformation = 1<<52;
66
67 }
68}
69
70#[derive(Debug, Clone, Copy, Eq, PartialEq)]
71pub struct TableRowCount(pub u32);
72
73impl TableRowCount {
74 pub fn is_large(&self) -> bool {
75 self.0 > u16::MAX as u32
76 }
77
78 pub fn row_size(&self) -> ValueSize {
79 if self.is_large() {
80 ValueSize::Big
81 } else {
82 ValueSize::Small
83 }
84 }
85}
86
87impl PartialEq<usize> for TableRowCount {
88 fn eq(&self, other: &usize) -> bool {
89 self.0 as usize == *other
90 }
91}
92
93#[derive(Debug, Clone)]
94pub struct TableRows {
95 pub module: TableRowCount,
96 pub type_ref: TableRowCount,
97 pub type_def: TableRowCount,
98 pub field_ptr: TableRowCount,
99 pub field: TableRowCount,
100 pub method_ptr: TableRowCount,
101 pub method: TableRowCount,
102 pub param_ptr: TableRowCount,
103 pub param: TableRowCount,
104 pub interface_impl: TableRowCount,
105 pub member_ref: TableRowCount,
106 pub constant: TableRowCount,
107 pub custom_attribute: TableRowCount,
108 pub field_marshal: TableRowCount,
109 pub decl_security: TableRowCount,
110 pub class_layout: TableRowCount,
111 pub field_layout: TableRowCount,
112 pub stand_alone_sig: TableRowCount,
113 pub event_map: TableRowCount,
114 pub event_ptr: TableRowCount,
115 pub event: TableRowCount,
116 pub property_map: TableRowCount,
117 pub property_ptr: TableRowCount,
118 pub property: TableRowCount,
119 pub method_semantics: TableRowCount,
120 pub method_impl: TableRowCount,
121 pub module_ref: TableRowCount,
122 pub type_spec: TableRowCount,
123 pub impl_map: TableRowCount,
124 pub field_rva: TableRowCount,
125 pub enc_log: TableRowCount,
126 pub enc_map: TableRowCount,
127 pub assembly: TableRowCount,
128 pub assembly_processor: TableRowCount,
129 pub assembly_os: TableRowCount,
130 pub assembly_ref: TableRowCount,
131 pub assembly_ref_processor: TableRowCount,
132 pub assembly_ref_os: TableRowCount,
133 pub file: TableRowCount,
134 pub exported_type: TableRowCount,
135 pub manifest_resource: TableRowCount,
136 pub nested_class: TableRowCount,
137 pub generic_param: TableRowCount,
138 pub method_spec: TableRowCount,
139 pub generic_param_constraint: TableRowCount,
140 pub document: TableRowCount,
141 pub method_debug_information: TableRowCount,
142 pub local_scope: TableRowCount,
143 pub local_variable: TableRowCount,
144 pub local_constant: TableRowCount,
145 pub import_scope: TableRowCount,
146 pub state_machine_method: TableRowCount,
147 pub custom_debug_information: TableRowCount,
148}
149
150impl TableRows {
151 pub fn from_reader(reader: &mut DataReader, valid_rows: TableExistsFlags) -> Result<Self> {
152 fn read_if_flag(
153 reader: &mut DataReader,
154 valid_rows: TableExistsFlags,
155 flag: TableExistsFlags,
156 ) -> Result<TableRowCount> {
157 if valid_rows.contains(flag) {
158 reader.read().map(TableRowCount)
159 } else {
160 Ok(TableRowCount(0))
161 }
162 }
163
164 Ok(Self {
165 module: read_if_flag(reader, valid_rows, TableExistsFlags::Module)?,
166 type_ref: read_if_flag(reader, valid_rows, TableExistsFlags::TypeRef)?,
167 type_def: read_if_flag(reader, valid_rows, TableExistsFlags::TypeDef)?,
168 field_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::FieldPtr)?,
169 field: read_if_flag(reader, valid_rows, TableExistsFlags::Field)?,
170 method_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::MethodPtr)?,
171 method: read_if_flag(reader, valid_rows, TableExistsFlags::Method)?,
172 param_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::ParamPtr)?,
173 param: read_if_flag(reader, valid_rows, TableExistsFlags::Param)?,
174 interface_impl: read_if_flag(reader, valid_rows, TableExistsFlags::InterfaceImpl)?,
175 member_ref: read_if_flag(reader, valid_rows, TableExistsFlags::MemberRef)?,
176 constant: read_if_flag(reader, valid_rows, TableExistsFlags::Constant)?,
177 custom_attribute: read_if_flag(reader, valid_rows, TableExistsFlags::CustomAttribute)?,
178 field_marshal: read_if_flag(reader, valid_rows, TableExistsFlags::FieldMarshal)?,
179 decl_security: read_if_flag(reader, valid_rows, TableExistsFlags::DeclSecurity)?,
180 class_layout: read_if_flag(reader, valid_rows, TableExistsFlags::ClassLayout)?,
181 field_layout: read_if_flag(reader, valid_rows, TableExistsFlags::FieldLayout)?,
182 stand_alone_sig: read_if_flag(reader, valid_rows, TableExistsFlags::StandAloneSig)?,
183 event_map: read_if_flag(reader, valid_rows, TableExistsFlags::EventMap)?,
184 event_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::EventPtr)?,
185 event: read_if_flag(reader, valid_rows, TableExistsFlags::Event)?,
186 property_map: read_if_flag(reader, valid_rows, TableExistsFlags::PropertyMap)?,
187 property_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::PropertyPtr)?,
188 property: read_if_flag(reader, valid_rows, TableExistsFlags::Property)?,
189 method_semantics: read_if_flag(reader, valid_rows, TableExistsFlags::MethodSemantics)?,
190 method_impl: read_if_flag(reader, valid_rows, TableExistsFlags::MethodImpl)?,
191 module_ref: read_if_flag(reader, valid_rows, TableExistsFlags::ModuleRef)?,
192 type_spec: read_if_flag(reader, valid_rows, TableExistsFlags::TypeSpec)?,
193 impl_map: read_if_flag(reader, valid_rows, TableExistsFlags::ImplMap)?,
194 field_rva: read_if_flag(reader, valid_rows, TableExistsFlags::FieldRva)?,
195 enc_log: read_if_flag(reader, valid_rows, TableExistsFlags::EncLog)?,
196 enc_map: read_if_flag(reader, valid_rows, TableExistsFlags::EncMap)?,
197 assembly: read_if_flag(reader, valid_rows, TableExistsFlags::Assembly)?,
198 assembly_processor: read_if_flag(
199 reader,
200 valid_rows,
201 TableExistsFlags::AssemblyProcessor,
202 )?,
203 assembly_os: read_if_flag(reader, valid_rows, TableExistsFlags::AssemblyOs)?,
204 assembly_ref: read_if_flag(reader, valid_rows, TableExistsFlags::AssemblyRef)?,
205 assembly_ref_processor: read_if_flag(
206 reader,
207 valid_rows,
208 TableExistsFlags::AssemblyRefProcessor,
209 )?,
210 assembly_ref_os: read_if_flag(reader, valid_rows, TableExistsFlags::AssemblyRefOs)?,
211 file: read_if_flag(reader, valid_rows, TableExistsFlags::File)?,
212 exported_type: read_if_flag(reader, valid_rows, TableExistsFlags::ExportedType)?,
213 manifest_resource: read_if_flag(
214 reader,
215 valid_rows,
216 TableExistsFlags::ManifestResource,
217 )?,
218 nested_class: read_if_flag(reader, valid_rows, TableExistsFlags::NestedClass)?,
219 generic_param: read_if_flag(reader, valid_rows, TableExistsFlags::GenericParam)?,
220 method_spec: read_if_flag(reader, valid_rows, TableExistsFlags::MethodSpec)?,
221 generic_param_constraint: read_if_flag(
222 reader,
223 valid_rows,
224 TableExistsFlags::GenericParamConstraint,
225 )?,
226 document: read_if_flag(reader, valid_rows, TableExistsFlags::Document)?,
227 method_debug_information: read_if_flag(
228 reader,
229 valid_rows,
230 TableExistsFlags::MethodDebugInformation,
231 )?,
232 local_scope: read_if_flag(reader, valid_rows, TableExistsFlags::LocalScope)?,
233 local_variable: read_if_flag(reader, valid_rows, TableExistsFlags::LocalVariable)?,
234 local_constant: read_if_flag(reader, valid_rows, TableExistsFlags::LocalConstant)?,
235 import_scope: read_if_flag(reader, valid_rows, TableExistsFlags::ImportScope)?,
236 state_machine_method: read_if_flag(
237 reader,
238 valid_rows,
239 TableExistsFlags::StateMachineMethod,
240 )?,
241 custom_debug_information: read_if_flag(
242 reader,
243 valid_rows,
244 TableExistsFlags::CustomDebugInformation,
245 )?,
246 })
247 }
248}
249
250#[derive(Debug, Clone)]
251pub struct TableLocations {
252 pub module: TableLocation,
253 pub type_ref: TableLocation,
254 pub type_def: TableLocation,
255 pub field_ptr: TableLocation,
256 pub field: TableLocation,
257 pub method_ptr: TableLocation,
258 pub method: TableLocation,
259 pub param_ptr: TableLocation,
260 pub param: TableLocation,
261 pub interface_impl: TableLocation,
262 pub member_ref: TableLocation,
263 pub constant: TableLocation,
264 pub custom_attribute: TableLocation,
265 pub field_marshal: TableLocation,
266 pub decl_security: TableLocation,
267 pub class_layout: TableLocation,
268 pub field_layout: TableLocation,
269 pub stand_alone_sig: TableLocation,
270 pub event_map: TableLocation,
271 pub event_ptr: TableLocation,
272 pub event: TableLocation,
273 pub property_map: TableLocation,
274 pub property_ptr: TableLocation,
275 pub property: TableLocation,
276 pub method_semantics: TableLocation,
277 pub method_impl: TableLocation,
278 pub module_ref: TableLocation,
279 pub type_spec: TableLocation,
280 pub impl_map: TableLocation,
281 pub field_rva: TableLocation,
282 pub enc_log: TableLocation,
283 pub enc_map: TableLocation,
284 pub assembly: TableLocation,
285 pub assembly_processor: TableLocation,
286 pub assembly_os: TableLocation,
287 pub assembly_ref: TableLocation,
288 pub assembly_ref_processor: TableLocation,
289 pub assembly_ref_os: TableLocation,
290 pub file: TableLocation,
291 pub exported_type: TableLocation,
292 pub manifest_resource: TableLocation,
293 pub nested_class: TableLocation,
294 pub generic_param: TableLocation,
295 pub method_spec: TableLocation,
296 pub generic_param_constraint: TableLocation,
297 pub document: TableLocation,
298 pub method_debug_information: TableLocation,
299 pub local_scope: TableLocation,
300 pub local_variable: TableLocation,
301 pub local_constant: TableLocation,
302 pub import_scope: TableLocation,
303 pub state_machine_method: TableLocation,
304 pub custom_debug_information: TableLocation,
305}
306
307impl TableLocations {
308 pub fn from_metadata(
309 rows: &TableRows,
310 coded_tokens_sizes: &CodedTokenSizes,
311 flags: MDStreamFlags,
312 version: Version,
313 ) -> Self {
314 let size_calculator = SizeCalculator {
315 coded_tokens_sizes,
316 flags,
317 rows,
318 version,
319 };
320 let mut calc = TablePositionCalculator::new(&size_calculator);
321 Self {
322 module: calc.calculate_location::<ModulesTableRow>(rows.module),
323 type_ref: calc.calculate_location::<TypeRefTableRow>(rows.type_ref),
324 type_def: calc.calculate_location::<TypeDefTableRow>(rows.type_def),
325 field_ptr: calc.calculate_location::<FieldPtrTableRow>(rows.field_ptr),
326 field: calc.calculate_location::<FieldTableRow>(rows.field),
327 method_ptr: calc.calculate_location::<MethodPtrTableRow>(rows.method_ptr),
328 method: calc.calculate_location::<MethodTableRow>(rows.method),
329 param_ptr: calc.calculate_location::<ParamPtrTableRow>(rows.param_ptr),
330 param: calc.calculate_location::<ParamTableRow>(rows.param),
331 interface_impl: calc.calculate_location::<InterfaceImplTableRow>(rows.interface_impl),
332 member_ref: calc.calculate_location::<MemberRefTableRow>(rows.member_ref),
333 constant: calc.calculate_location::<ConstantTableRow>(rows.constant),
334 custom_attribute: calc
335 .calculate_location::<CustomAttributeTableRow>(rows.custom_attribute),
336 field_marshal: calc.calculate_location::<FieldMarshalTableRow>(rows.field_marshal),
337 decl_security: calc.calculate_location::<DeclSecurityTableRow>(rows.decl_security),
338 class_layout: calc.calculate_location::<ClassLayoutTableRow>(rows.class_layout),
339 field_layout: calc.calculate_location::<FieldLayoutTableRow>(rows.field_layout),
340 stand_alone_sig: calc.calculate_location::<StandAloneSigTableRow>(rows.stand_alone_sig),
341 event_map: calc.calculate_location::<EventMapTableRow>(rows.event_map),
342 event_ptr: calc.calculate_location::<EventPtrTableRow>(rows.event_ptr),
343 event: calc.calculate_location::<EventTableRow>(rows.event),
344 property_map: calc.calculate_location::<PropertyMapTableRow>(rows.property_map),
345 property_ptr: calc.calculate_location::<PropertyPtrTableRow>(rows.property_ptr),
346 property: calc.calculate_location::<PropertyTableRow>(rows.property),
347 method_semantics: calc
348 .calculate_location::<MethodSemanticsTableRow>(rows.method_semantics),
349 method_impl: calc.calculate_location::<MethodImplTableRow>(rows.method_impl),
350 module_ref: calc.calculate_location::<ModuleRefTableRow>(rows.module_ref),
351 type_spec: calc.calculate_location::<TypeSpecTableRow>(rows.type_spec),
352 impl_map: calc.calculate_location::<ImplMapTableRow>(rows.impl_map),
353 field_rva: calc.calculate_location::<FieldRVATableRow>(rows.field_rva),
354 enc_log: calc.calculate_location::<ENCLogTableRow>(rows.enc_log),
355 enc_map: calc.calculate_location::<ENCMapTableRow>(rows.enc_map),
356 assembly: calc.calculate_location::<AssemblyTableRow>(rows.assembly),
357 assembly_processor: calc
358 .calculate_location::<AssemblyProcessorTableRow>(rows.assembly_processor),
359 assembly_os: calc.calculate_location::<AssemblyOSTableRow>(rows.assembly_os),
360 assembly_ref: calc.calculate_location::<AssemblyRefTableRow>(rows.assembly_ref),
361 assembly_ref_processor: calc
362 .calculate_location::<AssemblyRefProcessorTableRow>(rows.assembly_ref_processor),
363 assembly_ref_os: calc.calculate_location::<AssemblyRefOSTableRow>(rows.assembly_ref_os),
364 file: calc.calculate_location::<FileTableRow>(rows.file),
365 exported_type: calc.calculate_location::<ExportedTypeTableRow>(rows.exported_type),
366 manifest_resource: calc
367 .calculate_location::<ManifestResourceTableRow>(rows.manifest_resource),
368 nested_class: calc.calculate_location::<NestedClassTableRow>(rows.nested_class),
369 generic_param: calc.calculate_location::<GenericParamTableRow>(rows.generic_param),
370 method_spec: calc.calculate_location::<MethodSpecTableRow>(rows.method_spec),
371 generic_param_constraint: calc.calculate_location::<GenericParamConstraintTableRow>(
372 rows.generic_param_constraint,
373 ),
374 document: calc.calculate_location::<DocumentTableRow>(rows.document),
375 method_debug_information: calc.calculate_location::<MethodDebugInformationTableRow>(
376 rows.method_debug_information,
377 ),
378 local_scope: calc.calculate_location::<LocalScopeTableRow>(rows.local_scope),
379 local_variable: calc.calculate_location::<LocalVariableTableRow>(rows.local_variable),
380 local_constant: calc.calculate_location::<LocalConstantTableRow>(rows.local_constant),
381 import_scope: calc.calculate_location::<ImportScopeTableRow>(rows.import_scope),
382 state_machine_method: calc
383 .calculate_location::<StateMachineMethodTableRow>(rows.state_machine_method),
384 custom_debug_information: calc.calculate_location::<CustomDebugInformationTableRow>(
385 rows.custom_debug_information,
386 ),
387 }
388 }
389}