Struct SignaturePointer

pub struct SignaturePointer {
    pub modifiers: Vec<Token>,
    pub base: Box<TypeSignature>,
}
Expand description

Unmanaged pointer signature with custom modifiers.

Represents pointer types that directly reference unmanaged memory locations. Used primarily in unsafe code scenarios, platform invoke (P/Invoke) operations, and interoperability with native libraries.

§Pointer Characteristics

§Unmanaged Memory

Pointers reference memory that is not managed by the .NET garbage collector:

  • Manual memory management required
  • No automatic bounds checking
  • Direct memory address arithmetic
  • Potential for memory corruption if misused

§Type Safety

While pointers bypass many .NET safety features, they maintain type information:

int* intPtr;      // Points to int values
char* charPtr;    // Points to char values  
void* voidPtr;    // Points to untyped memory

§Unsafe Context Required

Pointer operations require unsafe code context:

unsafe {
    int value = 42;
    int* ptr = &value;          // Address-of operator
    int result = *ptr;          // Dereference operator
}

§Custom Modifiers for Pointers

Custom modifiers provide additional type information for advanced scenarios:

§Common Pointer Modifiers

  • Calling Conventions: Function pointer calling conventions
  • Memory Semantics: Volatile, const, restrict annotations
  • Platform Constraints: OS-specific pointer requirements
  • Interop Metadata: Native library compatibility information

§Example Modifier Uses

// These might generate custom modifiers:
const int* constPtr;               // modreq(IsConst)
volatile char* volatilePtr;        // modopt(IsVolatile)

§Binary Format (ECMA-335)

Pointer signatures are encoded as:

PTR [CustomMod*] <type>

Where:

  • PTR: Element type constant (0x0F)
  • [CustomMod*]: Optional custom modifier sequence
  • <type>: Pointed-to type signature

§Pointer Arithmetic

Pointers support arithmetic operations for memory navigation:

unsafe {
    int[] array = {1, 2, 3, 4, 5};
    fixed (int* ptr = array) {
        int* current = ptr;
        int* next = current + 1;     // Points to next int
        int* offset = ptr + 3;       // Points to array[3]
    }
}

§Safety Considerations

§Memory Safety

  • Dangling Pointers: Pointing to freed or invalid memory
  • Buffer Overflows: Accessing memory beyond allocated bounds
  • Type Confusion: Casting pointers to incompatible types
  • Memory Leaks: Forgetting to free allocated memory

§Best Practices

  • Minimize pointer usage scope
  • Use fixed statements for managed memory access
  • Validate pointer arithmetic bounds
  • Consider Span<T> and Memory<T> as safer alternatives

§Examples

§Simple Pointer Type

use dotscope::metadata::signatures::{SignaturePointer, TypeSignature};

let int_pointer = SignaturePointer {
    modifiers: vec![],                    // No custom modifiers
    base: Box::new(TypeSignature::I4),   // int* pointer
};

§Void Pointer

use dotscope::metadata::signatures::{SignaturePointer, TypeSignature};

let void_pointer = SignaturePointer {
    modifiers: vec![],
    base: Box::new(TypeSignature::Void),  // void* pointer
};

§Pointer with Custom Modifiers

use dotscope::metadata::signatures::{SignaturePointer, TypeSignature};
use dotscope::metadata::token::Token;

let const_pointer = SignaturePointer {
    modifiers: vec![
        Token::new(0x02000001),  // const modifier token
    ],
    base: Box::new(TypeSignature::Char),  // const char* pointer
};

§Function Pointer

Function pointers are represented differently using TypeSignature::FnPtr, but they share similar safety and usage characteristics:

delegate* unmanaged<int, int, int> funcPtr;  // Function pointer type

§Platform Invoke (P/Invoke)

Pointers are essential for P/Invoke operations:

[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(
    IntPtr lpAddress,        // Pointer parameter
    UIntPtr dwSize,
    uint flAllocationType,
    uint flProtect);

§ECMA-335 Compliance

This structure implements ECMA-335 Partition II, Section 23.2.11 (Pointer signature) and supports all standard pointer scenarios defined in the specification.

§See Also

Fields§

§modifiers: Vec<Token>

Custom modifiers that apply to the pointer type.

A vector of metadata tokens referencing TypeDef or TypeRef entries that specify additional constraints or annotations for the pointer. Most pointers have no custom modifiers (empty vector).

§Modifier Applications

  • Memory Semantics: const, volatile, restrict equivalents
  • Platform Constraints: OS-specific pointer requirements
  • Calling Conventions: Function pointer calling conventions
  • Safety Annotations: Tool-specific safety metadata

§Interop Scenarios

Custom modifiers are particularly important for P/Invoke and COM interop where native calling conventions and memory semantics must be preserved.

§base: Box<TypeSignature>

The type that this pointer references.

Can be any valid .NET type, though some combinations are more common:

  • Primitive Types: int*, char*, double*
  • Void Pointers: void* for untyped memory
  • Struct Pointers: Pointers to value types
  • Nested Pointers: int** (pointer to pointer)
  • Array Pointers: Pointers to array elements

§Special Cases

§Type Compatibility

Pointer types are compatible based on their pointed-to types:

  • Exact type matches are always compatible
  • void* can convert to/from any pointer type
  • Related types may be compatible with explicit casting

Trait Implementations§

§

impl Clone for SignaturePointer

§

fn clone(&self) -> SignaturePointer

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for SignaturePointer

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl Default for SignaturePointer

§

fn default() -> SignaturePointer

Returns the “default value” for a type. Read more
§

impl PartialEq for SignaturePointer

§

fn eq(&self, other: &SignaturePointer) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl StructuralPartialEq for SignaturePointer

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.