dotscope 0.6.0

A high-performance, cross-platform framework for analyzing and reverse engineering .NET PE executables
Documentation
//! Owned `StateMachineMethod` table representation for Portable PDB format
//!
//! This module provides the [`StateMachineMethod`] struct that represents
//! a fully resolved `StateMachineMethod` table entry with all indices converted
//! to proper metadata tokens for immediate use in debugging scenarios.

use crate::metadata::{method::MethodRc, token::Token};

/// Owned representation of a `StateMachineMethod` table entry
///
/// This structure contains the processed `StateMachineMethod` data with all table indices
/// resolved to their proper metadata tokens. This mapping is essential for debugging
/// async/await and iterator methods, as it allows debuggers to correlate the
/// compiler-generated state machine implementation with the original user code.
///
/// # State Machine Debugging
///
/// Modern C# and VB.NET features like async/await and yield return are implemented
/// using compiler-generated state machines. When debugging such code, several
/// challenges arise:
///
/// - Stack traces show confusing `MoveNext` method names
/// - Breakpoints set on async methods don't work as expected  
/// - Variable scopes and names are transformed by the compiler
/// - Step-through debugging becomes complex
///
/// The `StateMachineMethod` table solves these issues by providing the mapping
/// that allows debuggers to present a natural debugging experience.
///
/// # Usage Examples
///
/// ```rust,ignore
/// // Example C# async method:
/// // public async Task<int> CalculateAsync() { ... }
/// //
/// // The compiler generates:
/// // - Kickoff method: CalculateAsync (initializes state machine)
/// // - MoveNext method: <CalculateAsync>d__1.MoveNext (actual logic)
/// //
/// // StateMachineMethod entry links these together:
/// use dotscope::metadata::tables::StateMachineMethod;
///
/// let mapping = StateMachineMethod {
///     rid: 1,
///     token: Token::new(0x3600_0001),
///     offset: 0,
///     move_next_method: move_next_ref, // Strong reference to MoveNext method
///     kickoff_method: kickoff_ref,     // Strong reference to original method
/// };
/// ```
///
/// # References
///
/// - [Portable PDB Format - StateMachineMethod Table](https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#statemachinemethod-table-0x36)
/// - [C# Async/Await State Machines](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/)
#[derive(Clone)]
pub struct StateMachineMethod {
    /// Row identifier (1-based index in the table)
    pub rid: u32,

    /// Metadata token for this `StateMachineMethod` entry
    pub token: Token,

    /// Byte offset of this row in the original metadata stream
    pub offset: usize,

    /// Reference to the compiler-generated `MoveNext` method
    ///
    /// Strong reference to the state machine's `MoveNext` method that contains the actual
    /// implementation logic. This method is generated by the compiler and handles
    /// state transitions, await continuations, and yield return semantics.
    ///
    /// The method name typically follows patterns like:
    /// - `<OriginalMethodName>d__N.MoveNext` for async methods
    /// - `<OriginalMethodName>d__N.MoveNext` for iterator methods
    pub move_next_method: MethodRc,

    /// Reference to the original user-written kickoff method
    ///
    /// Strong reference to the method that was originally written by the developer.
    /// This method typically:
    /// - Creates and initializes the state machine instance
    /// - Returns a `Task`, `Task<T>`, or `IEnumerable<T>`
    /// - Contains minimal logic (just state machine setup)
    ///
    /// This is the method that appears in the user's source code and should
    /// be presented to the debugger as the "real" method being debugged.
    pub kickoff_method: MethodRc,
}