wdext 0.1.0

A DbgEng wrapper framework
// SPDX-FileCopyrightText: 2026 takubokudori
// SPDX-License-Identifier: MIT OR Apache-2.0
//! A wrapper around the DbgModel API.
//!
//! Work-in-progress
pub mod concept;
pub mod data_model_access;
pub mod data_model_concept;
pub mod data_model_manager;
pub mod host;
pub mod host_context;
pub mod host_evaluator;
pub mod host_memory;
pub mod host_module;
pub mod host_module_signature;
pub mod host_status;
pub mod host_symbol;
pub mod host_symbol_enumerator;
pub mod host_symbols;
pub mod host_type;
pub mod host_type_signature;
pub mod key_enumerator;
pub mod key_store;
pub mod model_method;
pub mod model_object;
pub mod model_property_accessor;
pub mod raw_enumerator;

pub use concept::*;
pub use data_model_access::*;
pub use data_model_concept::*;
pub use data_model_manager::*;
pub use host::*;
pub use host_context::*;
pub use host_evaluator::*;
pub use host_memory::*;
pub use host_module::*;
pub use host_module_signature::*;
pub use host_status::*;
pub use host_symbol::*;
pub use host_symbol_enumerator::*;
pub use host_symbols::*;
pub use host_type::*;
pub use host_type_signature::*;
pub use key_enumerator::*;
pub use key_store::*;
pub use model_method::*;
pub use model_object::*;
pub use model_property_accessor::*;
pub use raw_enumerator::*;

use crate::enum_flags;
use std::ffi::c_void;
use windows::Win32::System::Diagnostics::Debug::Extensions::{
    IDebugHostContext, ModelObjectKind, SignatureComparison, SymbolKind,
};
use windows_core::Interface;

enum_flags! {
    pub enum WdModelObjectKind: i32 {
        PropertyAccessor = 0,
        Context = 1,
        TargetObject = 2,
        TargetObjectReference = 3,
        Synthetic = 4,
        NoValue = 5,
        ObjectError = 6,
        Intrinsic = 7,
        Method = 8,
        KeyReference = 9,
    }
}

impl From<WdModelObjectKind> for ModelObjectKind {
    fn from(value: WdModelObjectKind) -> Self { ModelObjectKind(value as i32) }
}

enum_flags! {
    // [SymbolKind](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/dbgmodel/ne-dbgmodel-symbolkind)
    pub enum DbgModelSymbolKind: i32 {
        Unspecified = 0,
        Module = 1,
        Type = 2,
        Field = 3,
        Constant = 4,
        Data = 5,
        BaseClass = 6,
        Public = 7,
        Function = 8,
    }
}

impl From<SymbolKind> for DbgModelSymbolKind {
    fn from(value: SymbolKind) -> Self { Self::try_from(value.0).unwrap() }
}

impl From<DbgModelSymbolKind> for SymbolKind {
    fn from(value: DbgModelSymbolKind) -> Self { SymbolKind(value as i32) }
}

enum_flags! {
    pub enum DbgModelSignatureComparison: i32 {
        Unrelated = 0,
        Ambiguous = 1,
        LessSpecific = 2,
        MoreSpecific = 3,
        Identical = 4,
    }
}

impl From<SignatureComparison> for DbgModelSignatureComparison {
    fn from(value: SignatureComparison) -> Self {
        Self::try_from(value.0).unwrap()
    }
}

impl From<DbgModelSignatureComparison> for SignatureComparison {
    fn from(value: DbgModelSignatureComparison) -> Self {
        SignatureComparison(value as i32)
    }
}

pub enum NonNullHostContextBy<'a> {
    Context(&'a DebugHostContext),
    CurrentHostContext,
}

impl<'a> NonNullHostContextBy<'a> {
    pub fn current() -> Self { Self::CurrentHostContext }

    unsafe fn as_raw(&self) -> &IDebugHostContext {
        unsafe {
            match self {
                Self::Context(ctx) => ctx.as_raw(),
                Self::CurrentHostContext => {
                    IDebugHostContext::from_raw_borrowed(
                        &(usize::MAX as *mut c_void),
                    )
                    .unwrap()
                }
            }
        }
    }
}

impl<'a> From<&'a DebugHostContext> for NonNullHostContextBy<'a> {
    fn from(value: &'a DebugHostContext) -> Self { Self::Context(value) }
}

pub enum HostContextBy<'a> {
    Context(&'a DebugHostContext),
    CurrentHostContext,
    Nothing,
}

impl<'a> HostContextBy<'a> {
    unsafe fn as_raw(&self) -> &IDebugHostContext {
        unsafe {
            match self {
                Self::Context(ctx) => ctx.as_raw(),
                Self::CurrentHostContext => {
                    IDebugHostContext::from_raw_borrowed(
                        &(usize::MAX as *mut c_void),
                    )
                    .unwrap()
                }
                Self::Nothing => {
                    IDebugHostContext::from_raw_borrowed(&std::ptr::null_mut())
                        .unwrap()
                }
            }
        }
    }
}

impl<'a> From<&'a DebugHostContext> for HostContextBy<'a> {
    fn from(value: &'a DebugHostContext) -> Self { Self::Context(value) }
}

impl<'a> From<Option<&'a DebugHostContext>> for HostContextBy<'a> {
    fn from(value: Option<&'a DebugHostContext>) -> Self {
        match value {
            None => Self::Nothing,
            Some(ctx) => Self::Context(ctx),
        }
    }
}