wdext 0.1.0

A DbgEng wrapper framework
// SPDX-FileCopyrightText: 2026 takubokudori
// SPDX-License-Identifier: MIT OR Apache-2.0
//! IDebugSymbolGroup
use crate::dbgeng::*;
use windy::{ACPStr, ACPString, WStr, WString};

impl_debug_interface!(
    DebugSymbolGroup,
    DebugSymbolGroupRef,
    IDebugSymbolGroup2,
    IDebugSymbolGroup
);

// IDebugSymbolGroup
impl DebugSymbolGroup {
    pub fn get_number_symbols(&self) -> WinResult<u32> {
        unsafe { self.0.GetNumberSymbols() }
    }

    pub fn add_symbol(
        &self,
        name: impl AsRef<ACPStr>,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<SymbolGroupEntryIndex> {
        let mut ret = index.into();
        unsafe {
            self.0.AddSymbol(pca!(name), &mut ret)?;
            Ok(SymbolGroupEntryIndex::from(ret))
        }
    }

    pub fn remove_symbol_by_name(
        &self,
        name: impl AsRef<ACPStr>,
    ) -> WinResult<()> {
        unsafe { self.0.RemoveSymbolByName(pca!(name)) }
    }

    pub fn remove_symbol_by_index(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<()> {
        unsafe { self.0.RemoveSymbolByIndex(index.into()) }
    }

    pub fn get_symbol_name(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<ACPString> {
        unsafe {
            astring_with_capacity(128, |v, s| {
                vcall!(
                    self,
                    GetSymbolName,
                    index.into(),
                    pa!(v),
                    v.len().try_into().unwrap(),
                    s
                )
            })
        }
    }

    pub fn get_symbol_parameters(
        &self,
        start: SymbolGroupEntryIndex,
        count: u32,
    ) -> WinResult<Vec<DebugSymbolParameters>> {
        unsafe {
            let mut ret: Vec<DebugSymbolParameters> =
                Vec::with_capacity(count as usize);
            vcall!(
                self,
                GetSymbolParameters,
                start.into(),
                count,
                ret.as_mut_ptr() as *mut _
            )
            .ok()?;
            ret.set_len(count as usize);
            Ok(ret)
        }
    }

    pub fn expand_symbol(
        &self,
        index: SymbolGroupEntryIndex,
        expand: bool,
    ) -> WinResult<bool> {
        unsafe { hr!(vcall!(self, ExpandSymbol, index.into(), expand.into())) }
    }

    // OutputSymbols

    pub fn write_symbol(
        &self,
        index: SymbolGroupEntryIndex,
        value: impl AsRef<ACPStr>,
    ) -> WinResult<()> {
        unsafe { self.0.WriteSymbol(index.into(), pca!(value)) }
    }

    pub fn output_as_type(
        &self,
        index: SymbolGroupEntryIndex,
        r#type: impl AsRef<ACPStr>,
    ) -> WinResult<()> {
        unsafe { self.0.OutputAsType(index.into(), pca!(r#type)) }
    }
}

// IDebugSymbolGroup2
impl DebugSymbolGroup {
    pub fn add_symbol_wide(
        &self,
        name: impl AsRef<WStr>,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<SymbolGroupEntryIndex> {
        let mut ret = index.into();
        unsafe {
            self.0.AddSymbolWide(pcw!(name), &mut ret)?;
            Ok(SymbolGroupEntryIndex::from(ret))
        }
    }

    pub fn remove_symbol_by_name_wide(
        &self,
        name: impl AsRef<WStr>,
    ) -> WinResult<()> {
        unsafe { self.0.RemoveSymbolByNameWide(pcw!(name)) }
    }

    pub fn get_symbol_name_wide(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<WString> {
        unsafe {
            wstring_with_capacity(128, |v, s| {
                vcall!(
                    self,
                    GetSymbolNameWide,
                    index.into(),
                    pw!(v),
                    v.len().try_into().unwrap(),
                    s
                )
            })
        }
    }

    pub fn write_symbol_wide(
        &self,
        index: SymbolGroupEntryIndex,
        value: impl AsRef<WStr>,
    ) -> WinResult<()> {
        unsafe { self.0.WriteSymbolWide(index.into(), pcw!(value)) }
    }

    pub fn output_as_type_wide(
        &self,
        index: SymbolGroupEntryIndex,
        r#type: impl AsRef<WStr>,
    ) -> WinResult<()> {
        unsafe { self.0.OutputAsTypeWide(index.into(), pcw!(r#type)) }
    }

    pub fn get_symbol_type_name(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<ACPString> {
        unsafe {
            astring_with_capacity(128, |v, s| {
                vcall!(
                    self,
                    GetSymbolTypeName,
                    index.into(),
                    pa!(v),
                    v.len().try_into().unwrap(),
                    s
                )
            })
        }
    }

    pub fn get_symbol_type_name_wide(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<WString> {
        unsafe {
            wstring_with_capacity(128, |v, s| {
                vcall!(
                    self,
                    GetSymbolTypeNameWide,
                    index.into(),
                    pw!(v),
                    v.len().try_into().unwrap(),
                    s
                )
            })
        }
    }

    pub fn get_symbol_size(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<u32> {
        unsafe { self.0.GetSymbolSize(index.into()) }
    }

    pub fn get_symbol_offset(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<DebuggeeOffset> {
        unsafe { self.0.GetSymbolOffset(index.into()) }
    }

    pub fn get_symbol_register(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<RegisterIndex> {
        unsafe {
            Ok(RegisterIndex::from(self.0.GetSymbolRegister(index.into())?))
        }
    }

    pub fn get_symbol_value_text(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<ACPString> {
        unsafe {
            astring_with_capacity(128, |v, s| {
                vcall!(
                    self,
                    GetSymbolValueText,
                    index.into(),
                    pa!(v),
                    v.len().try_into().unwrap(),
                    s
                )
            })
        }
    }

    pub fn get_symbol_value_text_wide(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<WString> {
        unsafe {
            wstring_with_capacity(128, |v, s| {
                vcall!(
                    self,
                    GetSymbolValueTextWide,
                    index.into(),
                    pw!(v),
                    v.len().try_into().unwrap(),
                    s
                )
            })
        }
    }

    pub fn get_symbol_entry_information(
        &self,
        index: SymbolGroupEntryIndex,
    ) -> WinResult<DebugSymbolEntry> {
        unsafe {
            let mut entry: DebugSymbolEntry = std::mem::zeroed();
            self.0
                .GetSymbolEntryInformation(index.into(), &mut entry.0)?;
            Ok(entry)
        }
    }
}