hao 0.0.3

.net binary reader
Documentation
use super::coded_tokens::CodedTokenSizes;
use super::{tables::*, TableLocation, ValueSize};
use crate::dotnet::md::calculator::{SizeCalculator, TablePositionCalculator};
use crate::dotnet::md::streams::Version;
use crate::dotnet::md::MDStreamFlags;
use crate::io::ReadData;
use crate::{error::Result, io::DataReader};
use bitflags::bitflags;

bitflags! {
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub struct TableExistsFlags: u64 {
        const Module	= 1<<0;
        const TypeRef	= 1<<1;
        const TypeDef	= 1<<2;
        const FieldPtr	= 1<<3;
        const Field	    = 1<<4;
        const MethodPtr	= 1<<5;
        const Method	= 1<<6;
        const ParamPtr	= 1<<7;
        const Param	    = 1<<8;
        const InterfaceImpl	= 1<<9;
        const MemberRef	    = 1<<10;
        const Constant	    = 1<<11;
        const CustomAttribute	= 1<<12;
        const FieldMarshal	= 1<<13;
        const DeclSecurity	= 1<<14;
        const ClassLayout	= 1<<15;
        const FieldLayout	= 1<<16;
        const StandAloneSig	= 1<<17;
        const EventMap	= 1<<18;
        const EventPtr	= 1<<19;
        const Event	= 1<<20;
        const PropertyMap	= 1<<21;
        const PropertyPtr	= 1<<22;
        const Property	= 1<<23;
        const MethodSemantics	= 1<<24;
        const MethodImpl	= 1<<25;
        const ModuleRef	= 1<<26;
        const TypeSpec	= 1<<27;
        const ImplMap	= 1<<28;
        const FieldRva	= 1<<29;
        const EncLog	= 1<<30;
        const EncMap	= 1<<31;
        const Assembly	= 1<<32;
        const AssemblyProcessor	= 1<<33;
        const AssemblyOs	= 1<<34;
        const AssemblyRef	= 1<<35;
        const AssemblyRefProcessor	= 1<<36;
        const AssemblyRefOs	= 1<<37;
        const File	= 1<<38;
        const ExportedType	= 1<<39;
        const ManifestResource	= 1<<40;
        const NestedClass	= 1<<41;
        const GenericParam	= 1<<42;
        const MethodSpec	= 1<<43;
        const GenericParamConstraint	= 1<<44;
        const Document	= 1<<45;
        const MethodDebugInformation	= 1<<46;
        const LocalScope	= 1<<47;
        const LocalVariable	= 1<<48;
        const LocalConstant	= 1<<49;
        const ImportScope	= 1<<50;
        const StateMachineMethod	= 1<<51;
        const CustomDebugInformation	= 1<<52;

    }
}

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct TableRowCount(pub u32);

impl TableRowCount {
    pub fn is_large(&self) -> bool {
        self.0 > u16::MAX as u32
    }

    pub fn row_size(&self) -> ValueSize {
        if self.is_large() {
            ValueSize::Big
        } else {
            ValueSize::Small
        }
    }
}

impl PartialEq<usize> for TableRowCount {
    fn eq(&self, other: &usize) -> bool {
        self.0 as usize == *other
    }
}

#[derive(Debug, Clone)]
pub struct TableRows {
    pub module: TableRowCount,
    pub type_ref: TableRowCount,
    pub type_def: TableRowCount,
    pub field_ptr: TableRowCount,
    pub field: TableRowCount,
    pub method_ptr: TableRowCount,
    pub method: TableRowCount,
    pub param_ptr: TableRowCount,
    pub param: TableRowCount,
    pub interface_impl: TableRowCount,
    pub member_ref: TableRowCount,
    pub constant: TableRowCount,
    pub custom_attribute: TableRowCount,
    pub field_marshal: TableRowCount,
    pub decl_security: TableRowCount,
    pub class_layout: TableRowCount,
    pub field_layout: TableRowCount,
    pub stand_alone_sig: TableRowCount,
    pub event_map: TableRowCount,
    pub event_ptr: TableRowCount,
    pub event: TableRowCount,
    pub property_map: TableRowCount,
    pub property_ptr: TableRowCount,
    pub property: TableRowCount,
    pub method_semantics: TableRowCount,
    pub method_impl: TableRowCount,
    pub module_ref: TableRowCount,
    pub type_spec: TableRowCount,
    pub impl_map: TableRowCount,
    pub field_rva: TableRowCount,
    pub enc_log: TableRowCount,
    pub enc_map: TableRowCount,
    pub assembly: TableRowCount,
    pub assembly_processor: TableRowCount,
    pub assembly_os: TableRowCount,
    pub assembly_ref: TableRowCount,
    pub assembly_ref_processor: TableRowCount,
    pub assembly_ref_os: TableRowCount,
    pub file: TableRowCount,
    pub exported_type: TableRowCount,
    pub manifest_resource: TableRowCount,
    pub nested_class: TableRowCount,
    pub generic_param: TableRowCount,
    pub method_spec: TableRowCount,
    pub generic_param_constraint: TableRowCount,
    pub document: TableRowCount,
    pub method_debug_information: TableRowCount,
    pub local_scope: TableRowCount,
    pub local_variable: TableRowCount,
    pub local_constant: TableRowCount,
    pub import_scope: TableRowCount,
    pub state_machine_method: TableRowCount,
    pub custom_debug_information: TableRowCount,
}

impl TableRows {
    pub fn from_reader(reader: &mut DataReader, valid_rows: TableExistsFlags) -> Result<Self> {
        fn read_if_flag(
            reader: &mut DataReader,
            valid_rows: TableExistsFlags,
            flag: TableExistsFlags,
        ) -> Result<TableRowCount> {
            if valid_rows.contains(flag) {
                reader.read().map(TableRowCount)
            } else {
                Ok(TableRowCount(0))
            }
        }

        Ok(Self {
            module: read_if_flag(reader, valid_rows, TableExistsFlags::Module)?,
            type_ref: read_if_flag(reader, valid_rows, TableExistsFlags::TypeRef)?,
            type_def: read_if_flag(reader, valid_rows, TableExistsFlags::TypeDef)?,
            field_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::FieldPtr)?,
            field: read_if_flag(reader, valid_rows, TableExistsFlags::Field)?,
            method_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::MethodPtr)?,
            method: read_if_flag(reader, valid_rows, TableExistsFlags::Method)?,
            param_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::ParamPtr)?,
            param: read_if_flag(reader, valid_rows, TableExistsFlags::Param)?,
            interface_impl: read_if_flag(reader, valid_rows, TableExistsFlags::InterfaceImpl)?,
            member_ref: read_if_flag(reader, valid_rows, TableExistsFlags::MemberRef)?,
            constant: read_if_flag(reader, valid_rows, TableExistsFlags::Constant)?,
            custom_attribute: read_if_flag(reader, valid_rows, TableExistsFlags::CustomAttribute)?,
            field_marshal: read_if_flag(reader, valid_rows, TableExistsFlags::FieldMarshal)?,
            decl_security: read_if_flag(reader, valid_rows, TableExistsFlags::DeclSecurity)?,
            class_layout: read_if_flag(reader, valid_rows, TableExistsFlags::ClassLayout)?,
            field_layout: read_if_flag(reader, valid_rows, TableExistsFlags::FieldLayout)?,
            stand_alone_sig: read_if_flag(reader, valid_rows, TableExistsFlags::StandAloneSig)?,
            event_map: read_if_flag(reader, valid_rows, TableExistsFlags::EventMap)?,
            event_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::EventPtr)?,
            event: read_if_flag(reader, valid_rows, TableExistsFlags::Event)?,
            property_map: read_if_flag(reader, valid_rows, TableExistsFlags::PropertyMap)?,
            property_ptr: read_if_flag(reader, valid_rows, TableExistsFlags::PropertyPtr)?,
            property: read_if_flag(reader, valid_rows, TableExistsFlags::Property)?,
            method_semantics: read_if_flag(reader, valid_rows, TableExistsFlags::MethodSemantics)?,
            method_impl: read_if_flag(reader, valid_rows, TableExistsFlags::MethodImpl)?,
            module_ref: read_if_flag(reader, valid_rows, TableExistsFlags::ModuleRef)?,
            type_spec: read_if_flag(reader, valid_rows, TableExistsFlags::TypeSpec)?,
            impl_map: read_if_flag(reader, valid_rows, TableExistsFlags::ImplMap)?,
            field_rva: read_if_flag(reader, valid_rows, TableExistsFlags::FieldRva)?,
            enc_log: read_if_flag(reader, valid_rows, TableExistsFlags::EncLog)?,
            enc_map: read_if_flag(reader, valid_rows, TableExistsFlags::EncMap)?,
            assembly: read_if_flag(reader, valid_rows, TableExistsFlags::Assembly)?,
            assembly_processor: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::AssemblyProcessor,
            )?,
            assembly_os: read_if_flag(reader, valid_rows, TableExistsFlags::AssemblyOs)?,
            assembly_ref: read_if_flag(reader, valid_rows, TableExistsFlags::AssemblyRef)?,
            assembly_ref_processor: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::AssemblyRefProcessor,
            )?,
            assembly_ref_os: read_if_flag(reader, valid_rows, TableExistsFlags::AssemblyRefOs)?,
            file: read_if_flag(reader, valid_rows, TableExistsFlags::File)?,
            exported_type: read_if_flag(reader, valid_rows, TableExistsFlags::ExportedType)?,
            manifest_resource: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::ManifestResource,
            )?,
            nested_class: read_if_flag(reader, valid_rows, TableExistsFlags::NestedClass)?,
            generic_param: read_if_flag(reader, valid_rows, TableExistsFlags::GenericParam)?,
            method_spec: read_if_flag(reader, valid_rows, TableExistsFlags::MethodSpec)?,
            generic_param_constraint: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::GenericParamConstraint,
            )?,
            document: read_if_flag(reader, valid_rows, TableExistsFlags::Document)?,
            method_debug_information: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::MethodDebugInformation,
            )?,
            local_scope: read_if_flag(reader, valid_rows, TableExistsFlags::LocalScope)?,
            local_variable: read_if_flag(reader, valid_rows, TableExistsFlags::LocalVariable)?,
            local_constant: read_if_flag(reader, valid_rows, TableExistsFlags::LocalConstant)?,
            import_scope: read_if_flag(reader, valid_rows, TableExistsFlags::ImportScope)?,
            state_machine_method: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::StateMachineMethod,
            )?,
            custom_debug_information: read_if_flag(
                reader,
                valid_rows,
                TableExistsFlags::CustomDebugInformation,
            )?,
        })
    }
}

#[derive(Debug, Clone)]
pub struct TableLocations {
    pub module: TableLocation,
    pub type_ref: TableLocation,
    pub type_def: TableLocation,
    pub field_ptr: TableLocation,
    pub field: TableLocation,
    pub method_ptr: TableLocation,
    pub method: TableLocation,
    pub param_ptr: TableLocation,
    pub param: TableLocation,
    pub interface_impl: TableLocation,
    pub member_ref: TableLocation,
    pub constant: TableLocation,
    pub custom_attribute: TableLocation,
    pub field_marshal: TableLocation,
    pub decl_security: TableLocation,
    pub class_layout: TableLocation,
    pub field_layout: TableLocation,
    pub stand_alone_sig: TableLocation,
    pub event_map: TableLocation,
    pub event_ptr: TableLocation,
    pub event: TableLocation,
    pub property_map: TableLocation,
    pub property_ptr: TableLocation,
    pub property: TableLocation,
    pub method_semantics: TableLocation,
    pub method_impl: TableLocation,
    pub module_ref: TableLocation,
    pub type_spec: TableLocation,
    pub impl_map: TableLocation,
    pub field_rva: TableLocation,
    pub enc_log: TableLocation,
    pub enc_map: TableLocation,
    pub assembly: TableLocation,
    pub assembly_processor: TableLocation,
    pub assembly_os: TableLocation,
    pub assembly_ref: TableLocation,
    pub assembly_ref_processor: TableLocation,
    pub assembly_ref_os: TableLocation,
    pub file: TableLocation,
    pub exported_type: TableLocation,
    pub manifest_resource: TableLocation,
    pub nested_class: TableLocation,
    pub generic_param: TableLocation,
    pub method_spec: TableLocation,
    pub generic_param_constraint: TableLocation,
    pub document: TableLocation,
    pub method_debug_information: TableLocation,
    pub local_scope: TableLocation,
    pub local_variable: TableLocation,
    pub local_constant: TableLocation,
    pub import_scope: TableLocation,
    pub state_machine_method: TableLocation,
    pub custom_debug_information: TableLocation,
}

impl TableLocations {
    pub fn from_metadata(
        rows: &TableRows,
        coded_tokens_sizes: &CodedTokenSizes,
        flags: MDStreamFlags,
        version: Version,
    ) -> Self {
        let size_calculator = SizeCalculator {
            coded_tokens_sizes,
            flags,
            rows,
            version,
        };
        let mut calc = TablePositionCalculator::new(&size_calculator);
        Self {
            module: calc.calculate_location::<ModulesTableRow>(rows.module),
            type_ref: calc.calculate_location::<TypeRefTableRow>(rows.type_ref),
            type_def: calc.calculate_location::<TypeDefTableRow>(rows.type_def),
            field_ptr: calc.calculate_location::<FieldPtrTableRow>(rows.field_ptr),
            field: calc.calculate_location::<FieldTableRow>(rows.field),
            method_ptr: calc.calculate_location::<MethodPtrTableRow>(rows.method_ptr),
            method: calc.calculate_location::<MethodTableRow>(rows.method),
            param_ptr: calc.calculate_location::<ParamPtrTableRow>(rows.param_ptr),
            param: calc.calculate_location::<ParamTableRow>(rows.param),
            interface_impl: calc.calculate_location::<InterfaceImplTableRow>(rows.interface_impl),
            member_ref: calc.calculate_location::<MemberRefTableRow>(rows.member_ref),
            constant: calc.calculate_location::<ConstantTableRow>(rows.constant),
            custom_attribute: calc
                .calculate_location::<CustomAttributeTableRow>(rows.custom_attribute),
            field_marshal: calc.calculate_location::<FieldMarshalTableRow>(rows.field_marshal),
            decl_security: calc.calculate_location::<DeclSecurityTableRow>(rows.decl_security),
            class_layout: calc.calculate_location::<ClassLayoutTableRow>(rows.class_layout),
            field_layout: calc.calculate_location::<FieldLayoutTableRow>(rows.field_layout),
            stand_alone_sig: calc.calculate_location::<StandAloneSigTableRow>(rows.stand_alone_sig),
            event_map: calc.calculate_location::<EventMapTableRow>(rows.event_map),
            event_ptr: calc.calculate_location::<EventPtrTableRow>(rows.event_ptr),
            event: calc.calculate_location::<EventTableRow>(rows.event),
            property_map: calc.calculate_location::<PropertyMapTableRow>(rows.property_map),
            property_ptr: calc.calculate_location::<PropertyPtrTableRow>(rows.property_ptr),
            property: calc.calculate_location::<PropertyTableRow>(rows.property),
            method_semantics: calc
                .calculate_location::<MethodSemanticsTableRow>(rows.method_semantics),
            method_impl: calc.calculate_location::<MethodImplTableRow>(rows.method_impl),
            module_ref: calc.calculate_location::<ModuleRefTableRow>(rows.module_ref),
            type_spec: calc.calculate_location::<TypeSpecTableRow>(rows.type_spec),
            impl_map: calc.calculate_location::<ImplMapTableRow>(rows.impl_map),
            field_rva: calc.calculate_location::<FieldRVATableRow>(rows.field_rva),
            enc_log: calc.calculate_location::<ENCLogTableRow>(rows.enc_log),
            enc_map: calc.calculate_location::<ENCMapTableRow>(rows.enc_map),
            assembly: calc.calculate_location::<AssemblyTableRow>(rows.assembly),
            assembly_processor: calc
                .calculate_location::<AssemblyProcessorTableRow>(rows.assembly_processor),
            assembly_os: calc.calculate_location::<AssemblyOSTableRow>(rows.assembly_os),
            assembly_ref: calc.calculate_location::<AssemblyRefTableRow>(rows.assembly_ref),
            assembly_ref_processor: calc
                .calculate_location::<AssemblyRefProcessorTableRow>(rows.assembly_ref_processor),
            assembly_ref_os: calc.calculate_location::<AssemblyRefOSTableRow>(rows.assembly_ref_os),
            file: calc.calculate_location::<FileTableRow>(rows.file),
            exported_type: calc.calculate_location::<ExportedTypeTableRow>(rows.exported_type),
            manifest_resource: calc
                .calculate_location::<ManifestResourceTableRow>(rows.manifest_resource),
            nested_class: calc.calculate_location::<NestedClassTableRow>(rows.nested_class),
            generic_param: calc.calculate_location::<GenericParamTableRow>(rows.generic_param),
            method_spec: calc.calculate_location::<MethodSpecTableRow>(rows.method_spec),
            generic_param_constraint: calc.calculate_location::<GenericParamConstraintTableRow>(
                rows.generic_param_constraint,
            ),
            document: calc.calculate_location::<DocumentTableRow>(rows.document),
            method_debug_information: calc.calculate_location::<MethodDebugInformationTableRow>(
                rows.method_debug_information,
            ),
            local_scope: calc.calculate_location::<LocalScopeTableRow>(rows.local_scope),
            local_variable: calc.calculate_location::<LocalVariableTableRow>(rows.local_variable),
            local_constant: calc.calculate_location::<LocalConstantTableRow>(rows.local_constant),
            import_scope: calc.calculate_location::<ImportScopeTableRow>(rows.import_scope),
            state_machine_method: calc
                .calculate_location::<StateMachineMethodTableRow>(rows.state_machine_method),
            custom_debug_information: calc.calculate_location::<CustomDebugInformationTableRow>(
                rows.custom_debug_information,
            ),
        }
    }
}