Struct Guid
pub struct Guid<'a> { /* private fields */ }Expand description
ECMA-335 GUID heap providing indexed access to 128-bit globally unique identifiers.
The Guid struct represents the #GUID metadata heap according to ECMA-335 Section II.24.2.5.
It provides safe, zero-copy access to 16-byte GUID values referenced by metadata table entries
for assembly identification, type library correlation, and module tracking.
§GUID Heap Organization
§Storage Format
GUIDs are stored as consecutive 16-byte little-endian values:
- Each GUID occupies exactly 16 bytes
- No padding or alignment between entries
- Standard RFC 4122 UUID format within each 16-byte block
- Sequential storage enables efficient bulk operations
§Indexing Convention
The GUID heap uses 1-based indexing unlike other metadata heaps:
Index | Byte Offset | GUID Content
------|-------------|-------------
1 | 0-15 | First GUID
2 | 16-31 | Second GUID
3 | 32-47 | Third GUIDThis convention aligns with ECMA-335 requirements and metadata table references.
§GUID Types and Usage
§Assembly Identity GUIDs
Uniquely identify assemblies across application domains:
- Enable version-independent assembly correlation
- Support strong naming and security policies
- Facilitate debugging and profiling scenarios
§Type Library GUIDs
Support COM interoperability:
- Map .NET types to COM interfaces
- Enable marshalling between managed/unmanaged code
- Provide backward compatibility with legacy systems
§Module GUIDs
Distinguish modules within multi-module assemblies:
- Support incremental compilation workflows
- Enable fine-grained dependency tracking
- Facilitate debugging symbol correlation
§Examples
§Creating and Accessing GUIDs
use dotscope::metadata::streams::Guid;
// Sample GUID heap with two entries
#[rustfmt::skip]
let heap_data = [
// GUID 1: d437908e-65e6-487c-9735-7bdff699bea5
0x8e, 0x90, 0x37, 0xd4, 0xe6, 0x65, 0x7c, 0x48,
0x97, 0x35, 0x7b, 0xdf, 0xf6, 0x99, 0xbe, 0xa5,
// GUID 2: All zeros (null GUID)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let guid_heap = Guid::from(&heap_data)?;
// Access GUIDs using 1-based indexing (as per ECMA-335)
let assembly_guid = guid_heap.get(1)?;
let module_guid = guid_heap.get(2)?;
let null_guid = uguid::guid!("00000000-0000-0000-0000-000000000000");
assert_ne!(assembly_guid, null_guid);
assert_eq!(module_guid, null_guid);§Assembly Identity Verification
use dotscope::metadata::streams::Guid;
let heap_data = [0xAB; 16]; // Non-null GUID
let guid_heap = Guid::from(&heap_data)?;
let assembly_guid = guid_heap.get(1)?;
let null_guid = uguid::guid!("00000000-0000-0000-0000-000000000000");
// Check if assembly has unique identity
if assembly_guid != null_guid {
println!("Assembly ID: {}", assembly_guid);
// Use for caching, comparison, or security checks
}§Iterating Over All GUIDs
use dotscope::metadata::streams::Guid;
let heap_data = [0xFF; 32]; // Two GUIDs with pattern data
let guid_heap = Guid::from(&heap_data)?;
for result in &guid_heap {
let (index, guid) = result?;
println!("GUID {}: {}", index, guid);
}§Error Handling
Comprehensive error handling for various failure scenarios:
- Insufficient data: Heap smaller than minimum GUID size (16 bytes)
- Out of bounds: Invalid index or incomplete GUID data
- Invalid indexing: Index 0 or negative indices rejected
- Alignment issues: Proper 16-byte boundary validation
§ECMA-335 Compliance
This implementation fully supports ECMA-335 requirements:
- Correct 1-based indexing convention
- Proper 16-byte GUID storage alignment
- Little-endian byte order handling
- Standard RFC 4122 UUID format support
§See Also
crate::metadata::streams::guid::GuidIterator: For sequential access to all GUIDscrate::metadata::tables: For metadata tables referencing GUIDsuguid::Guid: The underlying GUID implementation- ECMA-335 II.24.2.5: Official specification
Implementations§
§impl<'a> Guid<'a>
impl<'a> Guid<'a>
pub fn from(data: &'a [u8]) -> Result<Guid<'a>>
pub fn from(data: &'a [u8]) -> Result<Guid<'a>>
Creates a new Guid heap accessor from raw metadata bytes.
Validates that the provided data contains sufficient bytes to represent at least one complete 16-byte GUID. The GUID heap stores sequential 128-bit globally unique identifiers referenced by metadata table entries.
§Parameters
data- Raw bytes containing the complete#GUIDheap data
§Returns
A Guid instance providing safe access to the heap contents, or an error
if the data format is invalid.
§Errors
Returns crate::Error in the following cases:
- Insufficient data: Less than 16 bytes provided (minimum for one GUID)
- Invalid alignment: Data length not divisible by 16 (partial GUID)
- Empty heap: No GUID data available for processing
§Examples
§Valid GUID Heap
use dotscope::metadata::streams::Guid;
// Single GUID heap (minimum valid size)
let single_guid = [0xAB; 16];
let guid_heap = Guid::from(&single_guid)?;
assert_eq!(guid_heap.get(1)?.to_bytes(), single_guid);
// Multiple GUID heap
let multiple_guids = [0xFF; 48]; // Three GUIDs
let guid_heap = Guid::from(&multiple_guids)?;
assert!(guid_heap.get(1).is_ok());
assert!(guid_heap.get(3).is_ok());§Invalid GUID Heap
use dotscope::metadata::streams::Guid;
// Too small for even one GUID
let too_small = [0u8; 10];
assert!(Guid::from(&too_small).is_err());
// Empty data
let empty_data = &[];
assert!(Guid::from(empty_data).is_err());§Assembly Identity Use Case
use dotscope::metadata::streams::Guid;
// Real assembly GUID from PE metadata
#[rustfmt::skip]
let assembly_heap = [
0x8e, 0x90, 0x37, 0xd4, 0xe6, 0x65, 0x7c, 0x48,
0x97, 0x35, 0x7b, 0xdf, 0xf6, 0x99, 0xbe, 0xa5,
];
let guid_heap = Guid::from(&assembly_heap)?;
let assembly_id = guid_heap.get(1)?;
// Use for assembly identification or caching
println!("Assembly GUID: {}", assembly_id);§Performance
- Zero-copy: No data is copied or allocated during construction
- O(1) validation: Only checks minimum size requirement
- Lazy parsing: GUID entries parsed only when accessed
- Memory efficient: Direct reference to source data
§GUID Heap Validation
This method performs minimal validation for performance:
- Ensures minimum 16-byte size for at least one GUID
- Does not validate GUID content or format
- Individual GUID access via
getprovides bounds checking
§See Also
get: Access individual GUIDs by 1-based indexiter: Iterate over all GUIDs in the heap- ECMA-335 II.24.2.5: GUID heap specification
pub fn get(&self, index: usize) -> Result<Guid>
pub fn get(&self, index: usize) -> Result<Guid>
Retrieves a GUID from the heap by its 1-based index.
Returns a constructed GUID from the 16-byte data stored at the specified index. The index typically comes from metadata table entries that reference specific GUIDs for assembly identity, type library correlation, or module identification.
§Parameters
index- 1-based GUID index within the heap (from metadata table references)
§Returns
A uguid::Guid constructed from the 16-byte data at the specified index,
or an error if the index is invalid or the data is insufficient.
§Errors
Returns crate::Error in the following cases:
- Invalid index: Index 0 (GUIDs use 1-based indexing per ECMA-335)
- Out of bounds: Index exceeds available GUID count
- Incomplete data: Insufficient bytes for complete 16-byte GUID
- Integer overflow: Index calculations exceed platform limits
§Examples
§Basic GUID Access
use dotscope::metadata::streams::Guid;
#[rustfmt::skip]
let heap_data = [
// GUID 1: d437908e-65e6-487c-9735-7bdff699bea5
0x8e, 0x90, 0x37, 0xd4, 0xe6, 0x65, 0x7c, 0x48,
0x97, 0x35, 0x7b, 0xdf, 0xf6, 0x99, 0xbe, 0xa5,
// GUID 2: All zeros (null GUID)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let guid_heap = Guid::from(&heap_data)?;
// Access first GUID (1-based indexing)
let first_guid = guid_heap.get(1)?;
let null_guid = uguid::guid!("00000000-0000-0000-0000-000000000000");
assert_ne!(first_guid, null_guid);
// Access second GUID
let second_guid = guid_heap.get(2)?;
assert_eq!(second_guid, null_guid);§Assembly Identity Example
use dotscope::metadata::streams::Guid;
// Assembly table references GUID index 1
let assembly_guid_index = 1;
let heap_data = [0xAB; 16]; // Sample assembly GUID
let guid_heap = Guid::from(&heap_data)?;
let assembly_guid = guid_heap.get(assembly_guid_index)?;
let null_guid = uguid::guid!("00000000-0000-0000-0000-000000000000");
// Use for assembly comparison or caching
if assembly_guid != null_guid {
println!("Assembly identifier: {}", assembly_guid);
}§Error Handling
use dotscope::metadata::streams::Guid;
let heap_data = [0xFF; 16]; // Single GUID heap
let guid_heap = Guid::from(&heap_data)?;
// Valid access
assert!(guid_heap.get(1).is_ok());
// Invalid index 0 (1-based indexing required)
assert!(guid_heap.get(0).is_err());
// Out of bounds access
assert!(guid_heap.get(2).is_err());§Performance
- O(1) access: Direct offset calculation and validation
- Zero-copy construction: GUID built from direct data reference
- Bounds checking: Full validation with minimal overhead
- Cache friendly: Sequential data access pattern
§Index Calculation
The byte offset for a GUID is calculated as (index - 1) * 16:
| Index | Byte Range | Description |
|---|---|---|
| 1 | 0-15 | First GUID |
| 2 | 16-31 | Second GUID |
| N | (N-1)16 to N16-1 | Nth GUID |
§GUID Format
Each 16-byte GUID follows RFC 4122 UUID format stored in little-endian byte order as specified by ECMA-335.
§See Also
iter: Iterate over all GUIDs sequentiallyuguid::Guid: The returned GUID type with formatting and comparison methods- ECMA-335 II.24.2.5: GUID heap specification
pub fn iter(&self) -> GuidIterator<'_> ⓘ
pub fn iter(&self) -> GuidIterator<'_> ⓘ
Returns an iterator over all GUIDs in the heap.
Provides sequential access to every GUID stored in the heap, yielding both the 1-based index and constructed GUID for each entry. This is useful for comprehensive analysis, validation, or enumeration of all assembly and module identifiers.
§Returns
Returns a crate::metadata::streams::guid::GuidIterator that yields Result<(usize, uguid::Guid)> tuples containing:
- Index: 1-based position of the GUID within the heap
- GUID: Constructed 128-bit globally unique identifier
§Iteration Behavior
- Sequential access: GUIDs returned in storage order (index 1, 2, 3, …)
- 1-based indexing: Consistent with ECMA-335 specification and
get()method - Complete iteration: Processes all valid GUIDs until heap end
- Error handling: Returns errors for malformed or incomplete GUID data
§Examples
§Basic Iteration
use dotscope::metadata::streams::Guid;
#[rustfmt::skip]
let heap_data = [
// GUID 1: Sample assembly identifier
0x8e, 0x90, 0x37, 0xd4, 0xe6, 0x65, 0x7c, 0x48,
0x97, 0x35, 0x7b, 0xdf, 0xf6, 0x99, 0xbe, 0xa5,
// GUID 2: Null GUID
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let guid_heap = Guid::from(&heap_data)?;
let null_guid = uguid::guid!("00000000-0000-0000-0000-000000000000");
for result in guid_heap.iter() {
let (index, guid) = result?;
println!("GUID {}: {}", index, guid);
if guid != null_guid {
println!(" Non-null identifier found");
}
}§Assembly and Module Enumeration
use dotscope::metadata::streams::Guid;
let heap_data = [0xAB; 48]; // Three identical GUIDs for demonstration
let guid_heap = Guid::from(&heap_data)?;
let mut assembly_guids = Vec::new();
let mut module_guids = Vec::new();
for result in guid_heap.iter() {
let (index, guid) = result?;
if index == 1 {
assembly_guids.push(guid);
} else {
module_guids.push(guid);
}
}
println!("Found {} assembly GUIDs, {} module GUIDs",
assembly_guids.len(), module_guids.len());§Error Handling During Iteration
use dotscope::metadata::streams::Guid;
let heap_data = [0xFF; 32]; // Two complete GUIDs
let guid_heap = Guid::from(&heap_data)?;
for result in guid_heap.iter() {
match result {
Ok((index, guid)) => {
println!("Valid GUID at index {}: {}", index, guid);
}
Err(e) => {
eprintln!("GUID parsing error: {}", e);
break; // Stop on first error
}
}
}§Collecting Non-Null GUIDs
use dotscope::metadata::streams::Guid;
let heap_data = [0x00; 32]; // Two null GUIDs
let guid_heap = Guid::from(&heap_data)?;
let null_guid = uguid::guid!("00000000-0000-0000-0000-000000000000");
let mut non_null_guids = Vec::new();
for result in guid_heap.iter() {
let (index, guid) = result?;
if guid != null_guid {
non_null_guids.push((index, guid));
}
}
println!("Found {} non-null GUIDs", non_null_guids.len());§Error Recovery
If a malformed GUID is encountered (e.g., due to heap truncation), the iterator returns an error and terminates. This design ensures data integrity while allowing partial processing of valid entries.
§Use Cases
- Assembly enumeration: Identify all assemblies in a multi-module application
- GUID validation: Verify heap integrity and detect corruption
- Debugging support: Display all identifiers for diagnostic purposes
- Metadata analysis: Extract identity information for processing
§See Also
crate::metadata::streams::guid::GuidIterator: The iterator implementation detailsget: Direct access to specific GUIDs by index- ECMA-335 II.24.2.5: GUID heap specification
Trait Implementations§
Auto Trait Implementations§
impl<'a> Freeze for Guid<'a>
impl<'a> RefUnwindSafe for Guid<'a>
impl<'a> Send for Guid<'a>
impl<'a> Sync for Guid<'a>
impl<'a> Unpin for Guid<'a>
impl<'a> UnwindSafe for Guid<'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