Struct TablesHeader
pub struct TablesHeader<'a> {
pub major_version: u8,
pub minor_version: u8,
pub valid: u64,
pub sorted: u64,
pub info: TableInfoRef,
/* private fields */
}Expand description
ECMA-335 compliant metadata tables header providing efficient access to .NET assembly metadata.
The crate::metadata::streams::tablesheader::TablesHeader struct represents the compressed metadata tables stream (#~) header
and provides type-safe, memory-efficient access to all metadata tables within a .NET assembly.
This is the primary interface for reflection, analysis, and runtime operations on .NET metadata.
§Architecture and Design
crate::metadata::streams::tablesheader::TablesHeader implements a lazy-loading design that maximizes performance
while maintaining memory safety through Rust’s lifetime system:
- Lazy parsing: Table rows are parsed only when accessed
- Type safety: Generic type parameters prevent incorrect table access
- Lifetime safety: Rust borrow checker prevents dangling references
- ECMA-335 compliance: Full specification adherence for all table formats
§Metadata Tables Overview
The metadata tables system contains 45 different table types defined by ECMA-335, each serving specific purposes in the .NET type system:
§Core Tables (Always Present)
- Module: Assembly module identification and versioning
TypeDef: Type definitions declared in this assemblyMethodDef: Method definitions and IL code referencesField: Field definitions and attributes
§Reference Tables (External Dependencies)
TypeRef: References to types in other assembliesMemberRef: References to methods/fields in external typesAssemblyRef: External assembly dependenciesModuleRef: Multi-module assembly references
§Relationship Tables (Type System Structure)
InterfaceImpl: Interface implementation relationshipsNestedClass: Nested type parent-child relationshipsGenericParam: Generic type and method parametersGenericParamConstraint: Generic parameter constraints
§Attribute and Metadata Tables
CustomAttribute: Custom attribute applicationsConstant: Compile-time constant valuesDeclSecurity: Declarative security permissionsFieldMarshal: Native interop marshalling specifications
§Thread Safety and Concurrency
crate::metadata::streams::tablesheader::TablesHeader provides comprehensive thread safety for concurrent metadata access:
- Immutable data: All table data read-only after construction
- Independent access: Multiple threads can access different tables safely
- Parallel iteration: Safe concurrent processing of table rows
- No synchronization: Zero contention between concurrent operations
§Examples
§Basic Table Access and Type Analysis
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, TypeDefRaw, MethodDefRaw}};
let tables = TablesHeader::from(tables_data)?;
// Safe table presence checking
if tables.has_table(TableId::TypeDef) {
let typedef_table = tables.table::<TypeDefRaw>().unwrap();
println!("Assembly defines {} types", typedef_table.row_count);
// Analyze type characteristics
for (index, type_def) in typedef_table.iter().enumerate().take(10) {
let is_public = type_def.flags & 0x00000007 == 0x00000001;
let is_sealed = type_def.flags & 0x00000100 != 0;
let is_abstract = type_def.flags & 0x00000080 != 0;
println!("Type {}: public={}, sealed={}, abstract={}",
index, is_public, is_sealed, is_abstract);
}
}§Cross-Table Relationship Analysis
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, TypeDefRaw, FieldRaw, MethodDefRaw}};
let tables = TablesHeader::from(tables_data)?;
// Analyze complete type structure with members
if let (Some(typedef_table), Some(field_table), Some(method_table)) = (
tables.table::<TypeDefRaw>(),
tables.table::<FieldRaw>(),
tables.table::<MethodDefRaw>()
) {
for (type_idx, type_def) in typedef_table.iter().enumerate().take(5) {
// Calculate member ranges for this type
let next_type = typedef_table.get((type_idx + 1) as u32);
let field_start = type_def.field_list.saturating_sub(1);
let field_end = next_type.as_ref()
.map(|t| t.field_list.saturating_sub(1))
.unwrap_or(field_table.row_count);
let method_start = type_def.method_list.saturating_sub(1);
let method_end = next_type.as_ref()
.map(|t| t.method_list.saturating_sub(1))
.unwrap_or(method_table.row_count);
println!("Type {}: {} fields, {} methods",
type_idx,
field_end.saturating_sub(field_start),
method_end.saturating_sub(method_start));
}
}§High-Performance Parallel Processing
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, CustomAttributeRaw}};
use rayon::prelude::*;
use std::collections::HashMap;
let tables = TablesHeader::from(tables_data)?;
// Parallel analysis of custom attributes
if let Some(ca_table) = tables.table::<CustomAttributeRaw>() {
// Process attributes in parallel for large assemblies
let attribute_analysis: HashMap<u32, u32> = ca_table.par_iter()
.map(|attr| {
// Extract parent table type from coded index
let parent_table = 1u32; // Simplified for documentation
(parent_table, 1u32)
})
.collect::<Vec<_>>()
.into_iter()
.fold(HashMap::new(), |mut acc, (table, count)| {
*acc.entry(table).or_insert(0) += count;
acc
});
println!("Custom attribute distribution:");
for (table_id, count) in attribute_analysis {
println!(" Table {}: {} attributes", table_id, count);
}
}§Memory-Efficient Large Table Processing
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, MemberRefRaw}};
let tables = TablesHeader::from(tables_data)?;
// Process large tables without loading all data into memory
if let Some(memberref_table) = tables.table::<MemberRefRaw>() {
const CHUNK_SIZE: u32 = 1000;
let total_rows = memberref_table.row_count;
println!("Processing {} member references in {} chunks",
total_rows, (total_rows + CHUNK_SIZE - 1) / CHUNK_SIZE);
let mut external_method_refs = 0;
let mut external_field_refs = 0;
// Process in chunks to manage memory usage
for chunk_start in (0..total_rows).step_by(CHUNK_SIZE as usize) {
let chunk_end = (chunk_start + CHUNK_SIZE).min(total_rows);
for i in chunk_start..chunk_end {
if let Some(member_ref) = memberref_table.get(i) {
// Analyze member reference type and parent
let is_method = true; // Simplified: check signature
let is_external = true; // Simplified: check class reference
if is_external {
if is_method {
external_method_refs += 1;
} else {
external_field_refs += 1;
}
}
}
}
}
println!("External references: {} methods, {} fields",
external_method_refs, external_field_refs);
}§Complete Assembly Introspection
use dotscope::metadata::{streams::TablesHeader, tables::TableId};
let tables = TablesHeader::from(tables_data)?;
println!("Assembly Metadata Analysis");
println!("=========================");
println!("Total tables: {}", tables.table_count());
println!();
// Analyze present tables and their characteristics
let summaries = tables.table_summary();
for summary in summaries {
match summary.table_id {
TableId::TypeDef => println!("✓ {} type definitions", summary.row_count),
TableId::MethodDef => println!("✓ {} method definitions", summary.row_count),
TableId::Field => println!("✓ {} field definitions", summary.row_count),
TableId::Assembly => println!("✓ Assembly metadata present"),
TableId::AssemblyRef => println!("✓ {} assembly references", summary.row_count),
TableId::CustomAttribute => println!("✓ {} custom attributes", summary.row_count),
TableId::GenericParam => println!("✓ {} generic parameters (generics used)", summary.row_count),
TableId::DeclSecurity => println!("✓ {} security declarations", summary.row_count),
TableId::ManifestResource => println!("✓ {} embedded resources", summary.row_count),
_ => println!("✓ {:?}: {} rows", summary.table_id, summary.row_count),
}
}
// Feature detection
println!();
println!("Assembly Features:");
if tables.has_table(TableId::GenericParam) {
println!(" ✓ Uses generic types/methods");
}
if tables.has_table(TableId::Event) {
println!(" ✓ Defines events");
}
if tables.has_table(TableId::Property) {
println!(" ✓ Defines properties");
}
if tables.has_table(TableId::DeclSecurity) {
println!(" ✓ Has security declarations");
}
if tables.has_table(TableId::ImplMap) {
println!(" ✓ Uses P/Invoke");
}§Security Considerations
§Input Validation
- ECMA-335 compliance: Strict adherence to specification format requirements
- Bounds checking: All table and row access validated against buffer boundaries
- Index validation: Cross-table references verified for correctness
- Size limits: Reasonable limits prevent resource exhaustion attacks
§Memory Safety
- Lifetime enforcement: Rust borrow checker prevents use-after-free vulnerabilities
- Type safety: Generic parameters prevent incorrect table type access
- Bounds verification: All array and slice access is bounds-checked
- Controlled unsafe: Minimal unsafe code with careful pointer management
§ECMA-335 Compliance
This implementation fully complies with ECMA-335 Partition II specifications:
- Section II.24.2.6: Metadata tables stream format and binary layout
- Section II.22: Complete metadata table definitions and relationships
- Compression format: Proper variable-width encoding for table indices
- Heap integration: Correct interpretation of string, blob, and GUID heap references
§See Also
crate::metadata::tables::MetadataTable: Individual table access and iterationcrate::metadata::tables::TableId: Enumeration of all supported table typescrate::metadata::streams: Overview of all metadata stream types- ECMA-335 II.24.2.6: Tables header specification
§Efficient Table Access Examples
§Basic Table Access
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, TypeDefRaw, MethodDefRaw, FieldRaw}};
// Check if a table is present before accessing it
if tables_header.has_table(TableId::TypeDef) {
// Get efficient access to the TypeDef table
if let Some(typedef_table) = tables_header.table::<TypeDefRaw>() {
println!("TypeDef table has {} rows", typedef_table.row_count);
// Access individual rows by index (0-based)
if let Some(first_type) = typedef_table.get(0) {
println!("First type: flags={}, name_idx={}, namespace_idx={}",
first_type.flags, first_type.type_name, first_type.type_namespace);
}
}
}§Iterating Over Table Rows
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, MethodDefRaw}};
// Iterate over all methods in the assembly
if let Some(method_table) = tables_header.table::<MethodDefRaw>() {
for (index, method) in method_table.iter().enumerate() {
println!("Method {}: RVA={:#x}, impl_flags={}, flags={}, name_idx={}",
index, method.rva, method.impl_flags, method.flags, method.name);
// Break after first 10 for demonstration
if index >= 9 { break; }
}
}§Parallel Processing with Rayon
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, FieldRaw}};
use rayon::prelude::*;
// Process field metadata in parallel
if let Some(field_table) = tables_header.table::<FieldRaw>() {
let field_count = field_table.par_iter()
.filter(|field| field.flags & 0x0010 != 0) // FieldAttributes.Static
.count();
println!("Found {} static fields", field_count);
}§Cross-Table Analysis
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, TypeDefRaw, MethodDefRaw}};
// Analyze types and their methods together
if let (Some(typedef_table), Some(method_table)) = (
tables_header.table::<TypeDefRaw>(),
tables_header.table::<MethodDefRaw>()
) {
for (type_idx, type_def) in typedef_table.iter().enumerate().take(5) {
println!("Type {}: methods {}-{}",
type_idx, type_def.method_list,
type_def.method_list.saturating_add(10)); // Simplified example
// In real usage, you'd calculate the actual method range
// by looking at the next type's method_list or using table bounds
}
}§Working with Table Summaries
use dotscope::metadata::streams::TablesHeader;
// Get overview of all present tables
let summaries = tables_header.table_summary();
for summary in summaries {
println!("Table {:?}: {} rows", summary.table_id, summary.row_count);
}
// Check for specific tables by ID
if tables_header.has_table_by_id(0x02) { // TypeDef table ID
println!("TypeDef table is present");
}
println!("Total metadata tables: {}", tables_header.table_count());§Memory-Efficient Pattern
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, CustomAttributeRaw}};
// Process large tables without loading all data at once
if let Some(ca_table) = tables_header.table::<CustomAttributeRaw>() {
println!("Processing {} custom attributes", ca_table.row_count);
// Process in chunks to manage memory usage
const CHUNK_SIZE: u32 = 100;
let total_rows = ca_table.row_count;
for chunk_start in (0..total_rows).step_by(CHUNK_SIZE as usize) {
let chunk_end = (chunk_start + CHUNK_SIZE).min(total_rows);
for i in chunk_start..chunk_end {
if let Some(attr) = ca_table.get(i) {
// Process individual custom attribute
// attr.parent, attr.type_def, attr.value are available
// without copying the entire table into memory
}
}
// Optional: yield control or log progress
println!("Processed chunk {}-{}", chunk_start, chunk_end);
}
}§Reference
- ‘https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf’ - II.24.2.6 && II.22
Fields§
§major_version: u8Major version of the metadata table schema, must be 2 per ECMA-335.
This field indicates the major version of the metadata table format. According to ECMA-335 Section II.24.2.6, this value must be 2 for all compliant .NET assemblies. Different major versions would indicate incompatible changes to the table format.
minor_version: u8Minor version of the metadata table schema, must be 0 per ECMA-335.
This field indicates the minor version of the metadata table format. The ECMA-335 specification requires this value to be 0. Minor version changes would indicate backward-compatible additions to the table format.
valid: u64Bit vector indicating which of the 64 possible metadata tables are present.
Each bit corresponds to a specific table ID (0-63) as defined in ECMA-335. A set bit (1) indicates the corresponding table is present and contains data. The number of set bits determines how many row count entries follow in the header.
§Table ID Mapping
- Bit 0: Module table
- Bit 1:
TypeReftable - Bit 2:
TypeDeftable - Bit 4: Field table
- Bit 6:
MethodDeftable - … (see ECMA-335 II.22 for complete mapping)
sorted: u64Bit vector indicating which metadata tables are sorted.
For each present table (indicated by valid), the corresponding bit in sorted
indicates whether that table’s rows are sorted according to ECMA-335 requirements.
Some tables must be sorted for binary search operations, while others may be
unsorted for faster insertion during metadata generation.
info: TableInfoRefShared table information containing row counts and heap index sizes.
This reference-counted structure provides efficient access to table metadata
including row counts for each present table and the size encoding for heap
indices (strings, blobs, GUIDs). The Arc allows multiple table instances
to share this information without duplication.
Implementations§
§impl<'a> TablesHeader<'a>
impl<'a> TablesHeader<'a>
pub fn from(data: &'a [u8]) -> Result<TablesHeader<'a>>
pub fn from(data: &'a [u8]) -> Result<TablesHeader<'a>>
Parse and construct a metadata tables header from binary data.
Creates a crate::metadata::streams::tablesheader::TablesHeader by parsing the compressed metadata tables stream (#~)
according to ECMA-335 Section II.24.2.6. This method performs comprehensive
validation of the stream format and constructs efficient access structures for
all present metadata tables.
§Binary Format Parsed
The method parses the following header structure:
Offset | Size | Field | Description
-------|------|--------------------|-----------------------------------------
0 | 4 | Reserved | Must be 0x00000000
4 | 1 | MajorVersion | Schema major version (must be 2)
5 | 1 | MinorVersion | Schema minor version (must be 0)
6 | 1 | HeapSizes | String/Blob/GUID heap index sizes
7 | 1 | Reserved | Must be 0x01
8 | 8 | Valid | Bit vector of present tables
16 | 8 | Sorted | Bit vector of sorted tables
24 | 4*N | Rows[] | Row counts for each present table
24+4*N | Var | TableData[] | Binary table data§Validation Performed
The method enforces ECMA-335 compliance through comprehensive validation:
- Minimum size: Data must contain complete header (≥24 bytes)
- Version checking: Major version must be 2, minor version must be 0
- Table presence: At least one table must be present (valid ≠ 0)
- Format integrity: Row count array and table data must be accessible
- Table structure: Each present table validated for proper format
§Construction Process
- Header parsing: Extract version, heap sizes, and table bit vectors
- Row count extraction: Read row counts for all present tables
- Table initialization: Parse each present table’s binary data
- Reference setup: Establish efficient access structures
- Validation: Verify all tables conform to ECMA-335 format
§Arguments
data- Complete binary data of the compressed metadata tables stream
§Returns
Ok(TablesHeader)- Successfully parsed and validated tables headerErr(Error)- Parsing failed due to format violations or insufficient data
§Errors
Returns crate::Error in the following cases:
crate::Error::OutOfBounds: Data too short for complete header (< 24 bytes)- Malformed data: No valid tables present (all bits in
validare 0) - Version error: Unsupported major/minor version combination
- Format error: Invalid table data or corrupted stream structure
- Table error: Individual table parsing failures due to malformed data
§Examples
§Basic Tables Header Construction
use dotscope::metadata::streams::TablesHeader;
// Read compressed metadata tables stream from assembly
let tables_stream_data = &[/* binary data from #~ stream */];
let tables = TablesHeader::from(tables_stream_data)?;
// Verify successful construction
println!("Parsed metadata with {} tables", tables.table_count());
println!("Schema version: {}.{}", tables.major_version, tables.minor_version);
// Check for common tables
use dotscope::metadata::tables::TableId;
if tables.has_table(TableId::TypeDef) {
println!("Assembly defines {} types", tables.table_row_count(TableId::TypeDef));
}
if tables.has_table(TableId::MethodDef) {
println!("Assembly defines {} methods", tables.table_row_count(TableId::MethodDef));
}§Error Handling and Validation
use dotscope::metadata::streams::TablesHeader;
// Error: Data too short
let too_short = [0u8; 20]; // Only 20 bytes, need at least 24
assert!(TablesHeader::from(&too_short).is_err());
// Error: No valid tables
let no_tables = [
0x00, 0x00, 0x00, 0x00, // Reserved
0x02, 0x00, // Version 2.0
0x01, 0x01, // HeapSizes, Reserved
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Valid = 0 (no tables)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sorted
];
assert!(TablesHeader::from(&no_tables).is_err());§Large Assembly Processing
use dotscope::metadata::streams::TablesHeader;
// Process large assembly with many tables
let large_assembly_data = &[/* large assembly #~ stream data */];
let start_time = std::time::Instant::now();
let tables = TablesHeader::from(large_assembly_data)?;
let parse_time = start_time.elapsed();
println!("Parsed {} tables in {:?}", tables.table_count(), parse_time);
// Analyze assembly size and complexity
let summaries = tables.table_summary();
let total_rows: u32 = summaries.iter().map(|s| s.row_count).sum();
println!("Assembly complexity:");
println!(" Total metadata rows: {}", total_rows);
println!(" Average rows per table: {:.1}",
total_rows as f64 / tables.table_count() as f64);
// Identify the most complex tables
let mut large_tables: Vec<_> = summaries.iter()
.filter(|s| s.row_count > 1000)
.collect();
large_tables.sort_by_key(|s| std::cmp::Reverse(s.row_count));
println!("Largest tables:");
for summary in large_tables.iter().take(3) {
println!(" {:?}: {} rows", summary.table_id, summary.row_count);
}§Assembly Feature Detection
use dotscope::metadata::{streams::TablesHeader, tables::TableId};
let assembly_data = &[/* assembly #~ stream data */];
let tables = TablesHeader::from(assembly_data)?;
println!("Assembly Feature Analysis:");
println!("=========================");
// Detect .NET framework features
if tables.has_table(TableId::GenericParam) {
let generic_count = tables.table_row_count(TableId::GenericParam);
println!("✓ Uses generics ({} parameters)", generic_count);
}
if tables.has_table(TableId::Event) {
let event_count = tables.table_row_count(TableId::Event);
println!("✓ Defines events ({} events)", event_count);
}
if tables.has_table(TableId::Property) {
let prop_count = tables.table_row_count(TableId::Property);
println!("✓ Defines properties ({} properties)", prop_count);
}
if tables.has_table(TableId::DeclSecurity) {
let security_count = tables.table_row_count(TableId::DeclSecurity);
println!("✓ Has security declarations ({} declarations)", security_count);
}
if tables.has_table(TableId::ImplMap) {
let pinvoke_count = tables.table_row_count(TableId::ImplMap);
println!("✓ Uses P/Invoke ({} mappings)", pinvoke_count);
}
if tables.has_table(TableId::ManifestResource) {
let resource_count = tables.table_row_count(TableId::ManifestResource);
println!("✓ Embeds resources ({} resources)", resource_count);
}§Thread Safety
Construction is thread-safe when called with different data sources.
The resulting crate::metadata::streams::tablesheader::TablesHeader instance is immutable and safe for concurrent
access across multiple threads.
§ECMA-335 Compliance
This method implements full ECMA-335 Partition II compliance:
- Section II.24.2.6: Metadata tables stream header format
- Section II.22: Individual table format specifications
- Compression format: Variable-width index encoding based on heap sizes
- Table relationships: Proper handling of cross-table references
§See Also
TablesHeader::table: Access individual metadata tables after constructionTablesHeader::table_summary: Get overview of all present tablescrate::metadata::tables::TableInfo: Table metadata and row count information- ECMA-335 II.24.2.6: Tables header specification
pub fn table_count(&self) -> u32
pub fn table_count(&self) -> u32
Get the total number of metadata tables present in this assembly.
Returns the count of tables that are actually present and contain data.
This is equivalent to the number of set bits in the valid field.
§Examples
use dotscope::metadata::streams::TablesHeader;
println!("Assembly contains {} metadata tables", tables.table_count());§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads.
pub fn table<T: RowReadable>(&'a self) -> Option<&'a MetadataTable<'a, T>>where
Self: TableAccess<'a, T>,
pub fn table<T: RowReadable>(&'a self) -> Option<&'a MetadataTable<'a, T>>where
Self: TableAccess<'a, T>,
Get a specific table for efficient access to metadata table rows.
This method provides safe, type-driven access to metadata tables without copying data. The returned table reference allows efficient iteration and random access to rows. The table type is automatically determined from the generic parameter, eliminating the need to specify table IDs and preventing type mismatches.
§Type Parameter
T- The table row type (e.g.,crate::metadata::tables::TypeDefRaw) The table ID is automatically inferred from the type parameter.
§Returns
Some(&MetadataTable<T>)- Reference to thecrate::metadata::tables::MetadataTableif presentNone- If the table is not present in this assembly
§Examples
use dotscope::metadata::{streams::TablesHeader, tables::TypeDefRaw};
// Safe, ergonomic access with automatic type inference
if let Some(typedef_table) = tables.table::<TypeDefRaw>() {
// Efficient access to all type definitions
for type_def in typedef_table.iter().take(5) {
println!("Type: flags={:#x}, name_idx={}, namespace_idx={}",
type_def.flags, type_def.type_name, type_def.type_namespace);
}
// Random access to specific rows
if let Some(first_type) = typedef_table.get(0) {
println!("First type name index: {}", first_type.type_name);
}
}§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads. The returned table reference is also safe for concurrent read access.
§Implementation Details
This method uses a trait to provide safe, compile-time verified table access. The trait implementation automatically maps each table type to its corresponding table ID, ensuring type safety without runtime overhead. No unsafe code is required.
pub fn has_table(&self, table_id: TableId) -> bool
pub fn has_table(&self, table_id: TableId) -> bool
Check if a specific metadata table is present in this assembly.
Use this method to safely check for table presence before accessing it. This avoids potential panics when working with assemblies that may not contain all possible metadata tables.
§Arguments
table_id- Thecrate::metadata::tables::TableIdto check for presence
§Examples
use dotscope::metadata::{streams::TablesHeader, tables::{TableId, EventRaw}};
/// Safe pattern: check before access
if tables.has_table(TableId::Event) {
if let Some(event_table) = tables.table::<EventRaw>() {
println!("Assembly has {} events", event_table.row_count);
}
} else {
println!("No events defined in this assembly");
}§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads.
pub fn has_table_by_id(&self, table_id: u8) -> bool
pub fn has_table_by_id(&self, table_id: u8) -> bool
Check if a metadata table is present by its numeric ID.
This method provides a way to check for table presence using the raw numeric table identifiers (0-63) as defined in the ECMA-335 specification.
§Arguments
table_id- The numeric table ID (0-63) to check for presence
§Returns
true- If the table is presentfalse- If the table is not present ortable_id> 63
§Examples
use dotscope::metadata::streams::TablesHeader;
// Check for specific tables by their numeric IDs
if tables.has_table_by_id(0x02) { // TypeDef
println!("TypeDef table present");
}
if tables.has_table_by_id(0x06) { // MethodDef
println!("MethodDef table present");
}
if tables.has_table_by_id(0x04) { // Field
println!("Field table present");
}§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads.
pub fn present_tables(&self) -> impl Iterator<Item = TableId> + '_
pub fn present_tables(&self) -> impl Iterator<Item = TableId> + '_
Get an iterator over all present metadata tables.
This method returns an iterator that yields crate::metadata::tables::TableId values for all tables
that are present in this assembly’s metadata. Useful for discovering what
metadata is available without having to check each table individually.
§Examples
use dotscope::metadata::streams::TablesHeader;
println!("Present metadata tables:");
for table_id in tables.present_tables() {
let row_count = tables.table_row_count(table_id);
println!(" {:?}: {} rows", table_id, row_count);
}§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads.
pub fn table_row_count(&self, table_id: TableId) -> u32
pub fn table_row_count(&self, table_id: TableId) -> u32
Get the row count for a specific metadata table.
Returns the number of rows in the specified table. This information is available even if you don’t access the table data itself.
§Arguments
table_id- Thecrate::metadata::tables::TableIdto get the row count for
§Returns
Row count (0 if table is not present)
§Examples
use dotscope::metadata::{streams::TablesHeader, tables::TableId};
let type_count = tables.table_row_count(TableId::TypeDef);
let method_count = tables.table_row_count(TableId::MethodDef);
let field_count = tables.table_row_count(TableId::Field);
println!("Assembly contains:");
println!(" {} types", type_count);
println!(" {} methods", method_count);
println!(" {} fields", field_count);§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads.
pub fn table_summary(&self) -> Vec<TableSummary>
pub fn table_summary(&self) -> Vec<TableSummary>
Get a summary of all present metadata tables with their row counts.
Returns a vector of summary structs containing the table ID and row count for each table present in this assembly. This provides an efficient way to get an overview of the assembly’s metadata structure without accessing individual tables.
§Examples
use dotscope::metadata::streams::TablesHeader;
let summaries = tables.table_summary();
for summary in summaries {
println!("Table {:?}: {} rows", summary.table_id, summary.row_count);
}§Thread Safety
This method is thread-safe and can be called concurrently from multiple threads.
pub fn write_header_to<W: Write>(&self, writer: &mut W) -> Result<()>
pub fn write_header_to<W: Write>(&self, writer: &mut W) -> Result<()>
Writes the tables stream header to a writer in ECMA-335 binary format.
Serializes the tables stream header including version info, heap sizes, valid/sorted table bitmasks, and row counts for present tables according to ECMA-335 Section II.24.2.6.
Note: This method writes only the header, not the actual table row data.
Table row data should be written separately using the RowWritable implementations.
§Binary Format Written
Offset | Size | Field | Description
-------|------|--------------|----------------------------------
0 | 4 | Reserved | Must be 0x00000000
4 | 1 | MajorVersion | Schema major version (2)
5 | 1 | MinorVersion | Schema minor version (0)
6 | 1 | HeapSizes | Heap index size flags
7 | 1 | Reserved | Must be 0x01
8 | 8 | Valid | Bit vector of present tables
16 | 8 | Sorted | Bit vector of sorted tables
24 | 4*N | Rows[] | Row counts for each present table§Arguments
writer- Any type implementingstd::io::Write
§Returns
Ok(())- Header written successfullyErr(Error)- Write operation failed
§Errors
Returns an error if writing to the writer fails.
§Examples
use dotscope::metadata::streams::TablesHeader;
let mut buffer = Vec::new();
tables.write_header_to(&mut buffer)?;
// Buffer now contains the serialized tables stream header
println!("Header size: {} bytes", buffer.len());pub fn header_size(&self) -> usize
pub fn header_size(&self) -> usize
Returns the serialized size of the tables stream header in bytes.
The size includes the fixed header fields (24 bytes) plus 4 bytes for each present table’s row count.
§Returns
The total size in bytes when written with write_header_to.
§Examples
use dotscope::metadata::streams::TablesHeader;
let header_size = tables.header_size();
println!("Tables stream header: {} bytes", header_size);Auto Trait Implementations§
impl<'a> Freeze for TablesHeader<'a>
impl<'a> RefUnwindSafe for TablesHeader<'a>
impl<'a> Send for TablesHeader<'a>
impl<'a> Sync for TablesHeader<'a>
impl<'a> Unpin for TablesHeader<'a>
impl<'a> UnwindSafe for TablesHeader<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more