use std::{ffi::c_void, slice};
use windows::{Win32::Foundation::E_POINTER, core::GUID};
use crate::{
WdResult, impl_ttd_view,
ttd::{cursor::Cursor, raw::bindings::*},
};
impl_ttd_view!(ReplayEngineView, IReplayEngineView);
#[derive(Debug, Clone, Copy)]
pub struct ThreadPositionIndices<'a> {
first: &'a [usize],
last: &'a [usize],
lifetime_first: &'a [usize],
lifetime_last: &'a [usize],
}
impl<'a> ThreadPositionIndices<'a> {
#[inline]
pub fn first(&self) -> &'a [usize] { self.first }
#[inline]
pub fn last(&self) -> &'a [usize] { self.last }
#[inline]
pub fn lifetime_first(&self) -> &'a [usize] { self.lifetime_first }
#[inline]
pub fn lifetime_last(&self) -> &'a [usize] { self.lifetime_last }
}
impl ReplayEngineView {
pub unsafe fn unsafe_as_interface(&self, iid: &GUID) -> *mut c_void {
unsafe { self.0.UnsafeAsInterface(iid) }
}
pub unsafe fn unsafe_as_interface_const(
&self,
iid: &GUID,
) -> *const c_void {
unsafe { self.0.UnsafeAsInterfaceConst(iid) }
}
#[inline]
pub fn get_peb_address(&self) -> GuestAddress {
unsafe { self.0.GetPebAddress() }
}
#[inline]
pub fn get_system_info(&self) -> SystemInfo {
unsafe { *self.0.GetSystemInfo() }
}
#[inline]
pub fn get_first_position(&self) -> Position {
unsafe { *self.0.GetFirstPosition() }
}
#[inline]
pub fn get_last_position(&self) -> Position {
unsafe { *self.0.GetLastPosition() }
}
#[inline]
pub fn get_lifetime(&self) -> PositionRange {
unsafe { *self.0.GetLifetime() }
}
#[inline]
pub fn get_recording_type(&self) -> RecordingType {
unsafe { self.0.GetRecordingType() }
}
#[inline]
pub fn get_thread_info(
&self,
unique_thread_id: UniqueThreadId,
) -> ThreadInfo {
unsafe { *self.0.GetThreadInfo(unique_thread_id) }
}
#[inline]
pub fn get_thread_count(&self) -> usize {
unsafe { self.0.GetThreadCount() }
}
#[inline]
pub fn get_thread_list(&self) -> *const ThreadInfo {
unsafe { self.0.GetThreadList() }
}
#[inline]
pub fn get_thread_first_position_index(&self) -> *const usize {
unsafe { self.0.GetThreadFirstPositionIndex() }
}
#[inline]
pub fn get_thread_last_position_index(&self) -> *const usize {
unsafe { self.0.GetThreadLastPositionIndex() }
}
#[inline]
pub fn get_thread_lifetime_first_position_index(&self) -> *const usize {
unsafe { self.0.GetThreadLifetimeFirstPositionIndex() }
}
#[inline]
pub fn get_thread_lifetime_last_position_index(&self) -> *const usize {
unsafe { self.0.GetThreadLifetimeLastPositionIndex() }
}
#[inline]
pub fn get_thread_created_event_count(&self) -> usize {
unsafe { self.0.GetThreadCreatedEventCount() }
}
#[inline]
pub fn get_thread_created_event_list(&self) -> *const ThreadCreatedEvent {
unsafe { self.0.GetThreadCreatedEventList() }
}
#[inline]
pub fn get_thread_terminated_event_count(&self) -> usize {
unsafe { self.0.GetThreadTerminatedEventCount() }
}
#[inline]
pub fn get_thread_terminated_event_list(
&self,
) -> *const ThreadTerminatedEvent {
unsafe { self.0.GetThreadTerminatedEventList() }
}
#[inline]
pub fn get_module_count(&self) -> usize {
unsafe { self.0.GetModuleCount() }
}
#[inline]
pub fn get_module_list(&self) -> *const Module {
unsafe { self.0.GetModuleList() }
}
#[inline]
pub fn get_module_instance_count(&self) -> usize {
unsafe { self.0.GetModuleInstanceCount() }
}
#[inline]
pub fn get_module_instance_list(&self) -> *const ModuleInstance {
unsafe { self.0.GetModuleInstanceList() }
}
#[inline]
pub fn get_module_instance_unload_index(&self) -> *const usize {
unsafe { self.0.GetModuleInstanceUnloadIndex() }
}
#[inline]
pub fn get_module_loaded_event_count(&self) -> usize {
unsafe { self.0.GetModuleLoadedEventCount() }
}
#[inline]
pub fn get_module_loaded_event_list(&self) -> *const ModuleLoadedEvent {
unsafe { self.0.GetModuleLoadedEventList() }
}
#[inline]
pub fn get_module_unloaded_event_count(&self) -> usize {
unsafe { self.0.GetModuleUnloadedEventCount() }
}
#[inline]
pub fn get_module_unloaded_event_list(&self) -> *const ModuleUnloadedEvent {
unsafe { self.0.GetModuleUnloadedEventList() }
}
#[inline]
pub fn get_exception_event_count(&self) -> usize {
unsafe { self.0.GetExceptionEventCount() }
}
#[inline]
pub fn get_exception_event_list(&self) -> *const ExceptionEvent {
unsafe { self.0.GetExceptionEventList() }
}
pub fn get_exception_at_or_after_position(
&self,
position: Position,
) -> Option<&ExceptionEvent> {
let ptr = unsafe { self.0.GetExceptionAtOrAfterPosition(position) };
unsafe { ptr.as_ref() }
}
#[inline]
pub fn get_keyframe_count(&self) -> usize {
unsafe { self.0.GetKeyframeCount() }
}
#[inline]
pub fn get_keyframe_list(&self) -> *const Position {
unsafe { self.0.GetKeyframeList() }
}
#[inline]
pub fn get_record_client_count(&self) -> usize {
unsafe { self.0.GetRecordClientCount() }
}
#[inline]
pub fn get_record_client_list(&self) -> *const RecordClient {
unsafe { self.0.GetRecordClientList() }
}
pub fn get_record_client(
&self,
id: RecordClientId,
) -> Option<&RecordClient> {
let ptr = unsafe { self.0.GetRecordClient(id) };
unsafe { ptr.as_ref() }
}
#[inline]
pub fn get_custom_event_count(&self) -> usize {
unsafe { self.0.GetCustomEventCount() }
}
#[inline]
pub fn get_custom_event_list(&self) -> *const CustomEvent {
unsafe { self.0.GetCustomEventList() }
}
#[inline]
pub fn get_activity_count(&self) -> usize {
unsafe { self.0.GetActivityCount() }
}
#[inline]
pub fn get_activity_list(&self) -> *const Activity {
unsafe { self.0.GetActivityList() }
}
#[inline]
pub fn get_island_count(&self) -> usize {
unsafe { self.0.GetIslandCount() }
}
#[inline]
pub fn get_island_list(&self) -> *const Island {
unsafe { self.0.GetIslandList() }
}
pub fn new_cursor(&self) -> WdResult<Cursor> {
let raw = unsafe { self.0.NewCursor() };
unsafe { Cursor::from_raw(raw) }.ok_or_else(|| E_POINTER.into())
}
pub unsafe fn build_index(
&self,
report_progress: IndexBuildProgressCallback,
caller_context: *const c_void,
flags: IndexBuildFlags,
) -> IndexStatus {
unsafe { self.0.BuildIndex(report_progress, caller_context, flags) }
}
#[inline]
pub fn get_index_status(&self) -> IndexStatus {
unsafe { self.0.GetIndexStatus() }
}
#[inline]
pub fn get_index_file_stats(&self) -> IndexFileStats {
unsafe { self.0.GetIndexFileStats() }
}
pub unsafe fn register_debug_mode_and_logging(
&self,
debug_mode: DebugModeType,
error_reporting: *mut ErrorReporting,
) {
unsafe {
self.0
.RegisterDebugModeAndLogging(debug_mode, error_reporting)
}
}
pub unsafe fn get_internals(&self) -> *mut IEngineInternals {
unsafe { self.0.GetInternals() }
}
pub unsafe fn get_internals_const(&self) -> *const IEngineInternals {
unsafe { self.0.GetInternalsConst() }
}
}
impl ReplayEngineView {
#[inline]
fn _ttd_slice<'a, T>(
&'a self,
ptr: *const T,
count: usize,
api: &'static str,
) -> &'a [T] {
if count == 0 {
return &[];
}
assert!(
!ptr.is_null(),
"TTD {api} returned null for a non-empty list"
);
unsafe { slice::from_raw_parts(ptr, count) }
}
pub fn _get_thread_list(&self) -> &[ThreadInfo] {
self._ttd_slice(
self.get_thread_list(),
self.get_thread_count(),
"GetThreadList",
)
}
pub fn _get_thread_position_indices(&self) -> ThreadPositionIndices<'_> {
let count = self.get_thread_count();
ThreadPositionIndices {
first: self._ttd_slice(
self.get_thread_first_position_index(),
count,
"GetThreadFirstPositionIndex",
),
last: self._ttd_slice(
self.get_thread_last_position_index(),
count,
"GetThreadLastPositionIndex",
),
lifetime_first: self._ttd_slice(
self.get_thread_lifetime_first_position_index(),
count,
"GetThreadLifetimeFirstPositionIndex",
),
lifetime_last: self._ttd_slice(
self.get_thread_lifetime_last_position_index(),
count,
"GetThreadLifetimeLastPositionIndex",
),
}
}
pub fn _get_thread_first_position_indices(&self) -> &[usize] {
self._ttd_slice(
self.get_thread_first_position_index(),
self.get_thread_count(),
"GetThreadFirstPositionIndex",
)
}
pub fn _get_thread_last_position_indices(&self) -> &[usize] {
self._ttd_slice(
self.get_thread_last_position_index(),
self.get_thread_count(),
"GetThreadLastPositionIndex",
)
}
pub fn _get_thread_lifetime_first_position_indices(&self) -> &[usize] {
self._ttd_slice(
self.get_thread_lifetime_first_position_index(),
self.get_thread_count(),
"GetThreadLifetimeFirstPositionIndex",
)
}
pub fn _get_thread_lifetime_last_position_indices(&self) -> &[usize] {
self._ttd_slice(
self.get_thread_lifetime_last_position_index(),
self.get_thread_count(),
"GetThreadLifetimeLastPositionIndex",
)
}
pub fn _get_thread_created_event_list(&self) -> &[ThreadCreatedEvent] {
self._ttd_slice(
self.get_thread_created_event_list(),
self.get_thread_created_event_count(),
"GetThreadCreatedEventList",
)
}
pub fn _get_thread_terminated_event_list(
&self,
) -> &[ThreadTerminatedEvent] {
self._ttd_slice(
self.get_thread_terminated_event_list(),
self.get_thread_terminated_event_count(),
"GetThreadTerminatedEventList",
)
}
pub fn _get_module_list(&self) -> &[Module] {
self._ttd_slice(
self.get_module_list(),
self.get_module_count(),
"GetModuleList",
)
}
pub fn _get_module_instance_list(&self) -> &[ModuleInstance] {
self._ttd_slice(
self.get_module_instance_list(),
self.get_module_instance_count(),
"GetModuleInstanceList",
)
}
pub fn _get_module_instance_unload_indices(&self) -> &[usize] {
self._ttd_slice(
self.get_module_instance_unload_index(),
self.get_module_instance_count(),
"GetModuleInstanceUnloadIndex",
)
}
pub fn _get_module_loaded_event_list(&self) -> &[ModuleLoadedEvent] {
self._ttd_slice(
self.get_module_loaded_event_list(),
self.get_module_loaded_event_count(),
"GetModuleLoadedEventList",
)
}
pub fn _get_module_unloaded_event_list(&self) -> &[ModuleUnloadedEvent] {
self._ttd_slice(
self.get_module_unloaded_event_list(),
self.get_module_unloaded_event_count(),
"GetModuleUnloadedEventList",
)
}
pub fn _get_exception_event_list(&self) -> &[ExceptionEvent] {
self._ttd_slice(
self.get_exception_event_list(),
self.get_exception_event_count(),
"GetExceptionEventList",
)
}
pub fn _get_keyframe_list(&self) -> &[Position] {
self._ttd_slice(
self.get_keyframe_list(),
self.get_keyframe_count(),
"GetKeyframeList",
)
}
pub fn _get_record_client_list(&self) -> &[RecordClient] {
self._ttd_slice(
self.get_record_client_list(),
self.get_record_client_count(),
"GetRecordClientList",
)
}
pub fn _get_custom_event_list(&self) -> &[CustomEvent] {
self._ttd_slice(
self.get_custom_event_list(),
self.get_custom_event_count(),
"GetCustomEventList",
)
}
pub fn _get_activity_list(&self) -> &[Activity] {
self._ttd_slice(
self.get_activity_list(),
self.get_activity_count(),
"GetActivityList",
)
}
pub fn _get_island_list(&self) -> &[Island] {
self._ttd_slice(
self.get_island_list(),
self.get_island_count(),
"GetIslandList",
)
}
}