wdext 0.1.0

A DbgEng wrapper framework
// SPDX-FileCopyrightText: 2026 takubokudori
// SPDX-License-Identifier: MIT OR Apache-2.0
use crate::{DebuggeeOffset, WdControl, WdResult, WideStrArg};
use std::{fmt, fmt::Formatter, marker::PhantomData, str::FromStr};

pub type I8EvalExpr = EvalExpr<EvalI8>;
pub type U8EvalExpr = EvalExpr<EvalU8>;
pub type I16EvalExpr = EvalExpr<EvalI16>;
pub type U16EvalExpr = EvalExpr<EvalU16>;
pub type I32EvalExpr = EvalExpr<EvalI32>;
pub type U32EvalExpr = EvalExpr<EvalU32>;
pub type U64EvalExpr = EvalExpr<EvalU64>;
pub type I64EvalExpr = EvalExpr<EvalI64>;
pub type USizeEvalExpr = EvalExpr<EvalUSize>;
pub type ISizeEvalExpr = EvalExpr<EvalISize>;
pub type PtrEvalExpr = EvalExpr<EvalPtr>;

macro_rules! impl_eval_expr {
    ($name:ident, $ty:ty) => {
        #[doc(hidden)]
        #[derive(Debug, Clone, Copy, Hash)]
        pub struct $name;

        impl DbgExprKind for $name {
            type Output = $ty;

            fn evaluate<'a>(
                control: impl AsRef<WdControl>,
                expression: impl Into<WideStrArg<'a>>,
            ) -> WdResult<Self::Output> {
                control.as_ref().evaluate_value::<$ty>(expression)
            }
        }
    };
}

pub trait DbgExprKind {
    type Output;

    fn evaluate<'a>(
        control: impl AsRef<WdControl>,
        expression: impl Into<WideStrArg<'a>>,
    ) -> WdResult<Self::Output>;
}

impl_eval_expr!(EvalI8, i8);
impl_eval_expr!(EvalU8, u8);
impl_eval_expr!(EvalI16, i16);
impl_eval_expr!(EvalU16, u16);
impl_eval_expr!(EvalI32, i32);
impl_eval_expr!(EvalU32, u32);
impl_eval_expr!(EvalI64, i64);
impl_eval_expr!(EvalU64, u64);
impl_eval_expr!(EvalISize, isize);
impl_eval_expr!(EvalUSize, usize);

#[doc(hidden)]
#[derive(Debug, Clone, Copy, Hash)]
pub struct EvalPtr;
impl DbgExprKind for EvalPtr {
    type Output = DebuggeeOffset;

    fn evaluate<'a>(
        control: impl AsRef<WdControl>,
        expression: impl Into<WideStrArg<'a>>,
    ) -> WdResult<Self::Output> {
        control.as_ref().evaluate_pointer(expression)
    }
}

#[derive(Debug, Clone, Hash)]
pub struct EvalExpr<K> {
    expression: String,
    _kind: PhantomData<fn() -> K>,
}

impl<K> EvalExpr<K> {
    /// Returns the debugger expression.
    pub fn expression(&self) -> &str { &self.expression }
}

impl<K> fmt::Display for EvalExpr<K> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str(&self.expression)
    }
}

impl<K: DbgExprKind> EvalExpr<K> {
    pub fn evaluate(
        &self,
        control: impl AsRef<WdControl>,
    ) -> WdResult<K::Output> {
        K::evaluate(control, &self.expression)
    }
}

impl<K> From<String> for EvalExpr<K> {
    fn from(expression: String) -> Self {
        Self {
            expression,
            _kind: PhantomData,
        }
    }
}

impl<K> From<&str> for EvalExpr<K> {
    fn from(expression: &str) -> Self { expression.to_owned().into() }
}

impl<K> FromStr for EvalExpr<K> {
    type Err = std::convert::Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(s.into()) }
}

impl<K> AsRef<str> for EvalExpr<K> {
    fn as_ref(&self) -> &str { self.expression() }
}