use crate::{
lldb_tid_t, sys, SBError, SBEvent, SBFrame, SBProcess, SBQueue, SBStream, SBValue, StopReason,
};
use std::ffi::CStr;
use std::fmt;
pub struct SBThread {
pub raw: sys::SBThreadRef,
}
impl SBThread {
pub fn maybe_wrap(raw: sys::SBThreadRef) -> Option<SBThread> {
if unsafe { sys::SBThreadIsValid(raw) } {
Some(SBThread { raw })
} else {
None
}
}
pub fn is_valid(&self) -> bool {
unsafe { sys::SBThreadIsValid(self.raw) }
}
#[allow(missing_docs)]
pub fn broadcaster_class_name() -> &'static str {
unsafe {
match CStr::from_ptr(sys::SBThreadGetBroadcasterClassName()).to_str() {
Ok(s) => s,
_ => panic!("Invalid string?"),
}
}
}
pub fn stop_reason(&self) -> StopReason {
unsafe { sys::SBThreadGetStopReason(self.raw) }
}
pub fn stop_return_value(&self) -> Option<SBValue> {
SBValue::maybe_wrap(unsafe { sys::SBThreadGetStopReturnValue(self.raw) })
}
pub fn thread_id(&self) -> lldb_tid_t {
unsafe { sys::SBThreadGetThreadID(self.raw) }
}
pub fn index_id(&self) -> u32 {
unsafe { sys::SBThreadGetIndexID(self.raw) }
}
pub fn name(&self) -> &str {
unsafe {
match CStr::from_ptr(sys::SBThreadGetName(self.raw)).to_str() {
Ok(s) => s,
_ => panic!("Invalid string?"),
}
}
}
pub fn queue(&self) -> Option<SBQueue> {
SBQueue::maybe_wrap(unsafe { sys::SBThreadGetQueue(self.raw) })
}
pub fn queue_name(&self) -> &str {
unsafe {
match CStr::from_ptr(sys::SBThreadGetQueueName(self.raw)).to_str() {
Ok(s) => s,
_ => panic!("Invalid string?"),
}
}
}
pub fn queue_id(&self) -> u64 {
unsafe { sys::SBThreadGetQueueID(self.raw) }
}
pub fn suspend(&self) -> Result<(), SBError> {
let error: SBError = SBError::default();
unsafe { sys::SBThreadSuspend(self.raw, error.raw) };
error.into_result()
}
pub fn resume(&self) -> Result<(), SBError> {
let error: SBError = SBError::default();
unsafe { sys::SBThreadResume(self.raw, error.raw) };
error.into_result()
}
pub fn is_suspended(&self) -> bool {
unsafe { sys::SBThreadIsSuspended(self.raw) }
}
pub fn is_stopped(&self) -> bool {
unsafe { sys::SBThreadIsStopped(self.raw) }
}
pub fn frames(&self) -> SBThreadFrameIter {
SBThreadFrameIter {
thread: self,
idx: 0,
}
}
pub fn selected_frame(&self) -> SBFrame {
SBFrame::from(unsafe { sys::SBThreadGetSelectedFrame(self.raw) })
}
pub fn set_selected_frame(&self, frame_index: u32) -> Option<SBFrame> {
SBFrame::maybe_wrap(unsafe { sys::SBThreadSetSelectedFrame(self.raw, frame_index) })
}
pub fn process(&self) -> SBProcess {
SBProcess::from(unsafe { sys::SBThreadGetProcess(self.raw) })
}
pub fn event_as_thread_event(event: &SBEvent) -> Option<SBThreadEvent> {
if unsafe { sys::SBThreadEventIsThreadEvent(event.raw) } {
Some(SBThreadEvent::new(event))
} else {
None
}
}
}
pub struct SBThreadFrameIter<'d> {
thread: &'d SBThread,
idx: usize,
}
impl<'d> Iterator for SBThreadFrameIter<'d> {
type Item = SBFrame;
fn next(&mut self) -> Option<SBFrame> {
if self.idx < unsafe { sys::SBThreadGetNumFrames(self.thread.raw) as usize } {
let r = Some(SBFrame::from(unsafe {
sys::SBThreadGetFrameAtIndex(self.thread.raw, self.idx as u32)
}));
self.idx += 1;
r
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = unsafe { sys::SBThreadGetNumFrames(self.thread.raw) } as usize;
(sz - self.idx, Some(sz))
}
}
impl<'d> ExactSizeIterator for SBThreadFrameIter<'d> {}
impl Clone for SBThread {
fn clone(&self) -> SBThread {
SBThread {
raw: unsafe { sys::CloneSBThread(self.raw) },
}
}
}
impl fmt::Debug for SBThread {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let stream = SBStream::new();
unsafe { sys::SBThreadGetDescription(self.raw, stream.raw) };
write!(fmt, "SBThread {{ {} }}", stream.data())
}
}
impl Drop for SBThread {
fn drop(&mut self) {
unsafe { sys::DisposeSBThread(self.raw) };
}
}
impl From<sys::SBThreadRef> for SBThread {
fn from(raw: sys::SBThreadRef) -> SBThread {
SBThread { raw }
}
}
unsafe impl Send for SBThread {}
unsafe impl Sync for SBThread {}
pub struct SBThreadEvent<'e> {
event: &'e SBEvent,
}
impl<'e> SBThreadEvent<'e> {
pub fn new(event: &'e SBEvent) -> Self {
SBThreadEvent { event }
}
pub fn thread(&self) -> SBThread {
SBThread::from(unsafe { sys::SBThreadGetThreadFromEvent(self.event.raw) })
}
pub fn frame(&self) -> Option<SBFrame> {
SBFrame::maybe_wrap(unsafe { sys::SBThreadGetStackFrameFromEvent(self.event.raw) })
}
}
#[cfg(feature = "graphql")]
graphql_object!(SBThread: crate::SBDebugger | &self | {
field is_valid() -> bool {
self.is_valid()
}
field thread_id() -> i32 {
self.thread_id() as i32
}
field index_id() -> i32 {
self.index_id() as i32
}
field frames() -> Vec<SBFrame> {
self.frames().collect()
}
field selected_frame() -> SBFrame {
self.selected_frame()
}
field process() -> SBProcess {
self.process()
}
});