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> {
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() }
}