hao/dotnet/md/streams/tables_stream/
metadata.rs

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}