use crate::{
sys, SBCommandInterpreter, SBError, SBListener, SBPlatform, SBStream, SBStructuredData,
SBTarget,
};
use std::ffi::{CStr, CString};
use std::fmt;
use std::iter;
use std::ptr;
pub struct SBDebugger {
pub raw: sys::SBDebuggerRef,
}
impl SBDebugger {
pub fn initialize() {
unsafe { sys::SBDebuggerInitialize() };
}
pub fn terminate() {
unsafe { sys::SBDebuggerTerminate() };
}
pub fn create(source_init_files: bool) -> SBDebugger {
SBDebugger {
raw: unsafe { sys::SBDebuggerCreate2(source_init_files) },
}
}
pub fn asynchronous(&self) -> bool {
unsafe { sys::SBDebuggerGetAsync(self.raw) }
}
pub fn set_asynchronous(&self, asynchronous: bool) {
unsafe { sys::SBDebuggerSetAsync(self.raw, asynchronous) }
}
#[allow(missing_docs)]
pub fn command_interpreter(&self) -> SBCommandInterpreter {
SBCommandInterpreter::wrap(unsafe { sys::SBDebuggerGetCommandInterpreter(self.raw) })
}
pub fn enable_log(&self, channel: &str, categories: &[&str]) -> bool {
let channel = CString::new(channel).unwrap();
let categories: Vec<_> = categories
.iter()
.map(|&s| CString::new(s).unwrap())
.collect();
let categories_ptr: Vec<_> = categories
.iter()
.map(|s| s.as_ptr())
.chain(iter::once(ptr::null()))
.collect();
unsafe { sys::SBDebuggerEnableLog(self.raw, channel.as_ptr(), categories_ptr.as_ptr()) }
}
pub fn version() -> String {
unsafe {
match CStr::from_ptr(sys::SBDebuggerGetVersionString()).to_str() {
Ok(s) => s.to_owned(),
_ => panic!("No version string?"),
}
}
}
pub fn create_target(
&self,
executable: &str,
target_triple: Option<&str>,
platform_name: Option<&str>,
add_dependent_modules: bool,
) -> Result<SBTarget, SBError> {
let executable = CString::new(executable).unwrap();
let target_triple = target_triple.map(|s| CString::new(s).unwrap());
let platform_name = platform_name.map(|s| CString::new(s).unwrap());
let error = SBError::default();
let target = unsafe {
sys::SBDebuggerCreateTarget(
self.raw,
executable.as_ptr(),
target_triple.map_or(ptr::null(), |s| s.as_ptr()),
platform_name.map_or(ptr::null(), |s| s.as_ptr()),
add_dependent_modules,
error.raw,
)
};
if error.is_success() {
Ok(SBTarget::wrap(target))
} else {
Err(error)
}
}
pub fn create_target_simple(&self, executable: &str) -> Option<SBTarget> {
let executable = CString::new(executable).unwrap();
SBTarget::maybe_wrap(unsafe { sys::SBDebuggerCreateTarget2(self.raw, executable.as_ptr()) })
}
pub fn targets(&self) -> SBDebuggerTargetIter {
SBDebuggerTargetIter {
debugger: self,
idx: 0,
}
}
pub fn listener(&self) -> SBListener {
SBListener::wrap(unsafe { sys::SBDebuggerGetListener(self.raw) })
}
pub fn selected_target(&self) -> Option<SBTarget> {
SBTarget::maybe_wrap(unsafe { sys::SBDebuggerGetSelectedTarget(self.raw) })
}
pub fn set_selected_target(&self, target: &SBTarget) {
unsafe { sys::SBDebuggerSetSelectedTarget(self.raw, target.raw) };
}
pub fn platforms(&self) -> SBDebuggerPlatformIter {
SBDebuggerPlatformIter {
debugger: self,
idx: 0,
}
}
pub fn selected_platform(&self) -> SBPlatform {
unsafe {
SBPlatform {
raw: sys::SBDebuggerGetSelectedPlatform(self.raw),
}
}
}
pub fn set_selected_platform(&self, platform: &SBPlatform) {
unsafe { sys::SBDebuggerSetSelectedPlatform(self.raw, platform.raw) };
}
pub fn available_platforms(&self) -> SBDebuggerAvailablePlatformIter {
SBDebuggerAvailablePlatformIter {
debugger: self,
idx: 0,
}
}
pub fn set_current_platform(&self, platform_name: &str) {
let platform_name = CString::new(platform_name).unwrap();
unsafe { sys::SBDebuggerSetCurrentPlatform(self.raw, platform_name.as_ptr()) };
}
#[allow(missing_docs)]
pub fn set_current_platform_sdk_root(&self, sysroot: &str) {
let sysroot = CString::new(sysroot).unwrap();
unsafe { sys::SBDebuggerSetCurrentPlatformSDKRoot(self.raw, sysroot.as_ptr()) };
}
#[allow(missing_docs)]
pub fn set_use_external_editor(&self, use_external_editor: bool) {
unsafe { sys::SBDebuggerSetUseExternalEditor(self.raw, use_external_editor) };
}
#[allow(missing_docs)]
pub fn get_use_external_editor(&self) -> bool {
unsafe { sys::SBDebuggerGetUseExternalEditor(self.raw) }
}
#[allow(missing_docs)]
pub fn set_use_color(&self, use_color: bool) {
unsafe { sys::SBDebuggerSetUseColor(self.raw, use_color) };
}
#[allow(missing_docs)]
pub fn get_use_color(&self) -> bool {
unsafe { sys::SBDebuggerGetUseColor(self.raw) }
}
#[allow(missing_docs)]
pub fn set_use_source_cache(&self, use_source_cache: bool) {
unsafe { sys::SBDebuggerSetUseSourceCache(self.raw, use_source_cache) };
}
#[allow(missing_docs)]
pub fn get_use_source_cache(&self) -> bool {
unsafe { sys::SBDebuggerGetUseSourceCache(self.raw) }
}
}
pub struct SBDebuggerTargetIter<'d> {
debugger: &'d SBDebugger,
idx: usize,
}
impl<'d> Iterator for SBDebuggerTargetIter<'d> {
type Item = SBTarget;
fn next(&mut self) -> Option<SBTarget> {
if self.idx < unsafe { sys::SBDebuggerGetNumTargets(self.debugger.raw) as usize } {
let r = Some(SBTarget {
raw: unsafe { sys::SBDebuggerGetTargetAtIndex(self.debugger.raw, self.idx as u32) },
});
self.idx += 1;
r
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = unsafe { sys::SBDebuggerGetNumTargets(self.debugger.raw) } as usize;
(sz - self.idx, Some(sz))
}
}
impl<'d> ExactSizeIterator for SBDebuggerTargetIter<'d> {}
impl Clone for SBDebugger {
fn clone(&self) -> SBDebugger {
SBDebugger {
raw: unsafe { sys::CloneSBDebugger(self.raw) },
}
}
}
impl fmt::Debug for SBDebugger {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let stream = SBStream::new();
unsafe { sys::SBDebuggerGetDescription(self.raw, stream.raw) };
write!(fmt, "SBDebugger {{ {} }}", stream.data())
}
}
impl Drop for SBDebugger {
fn drop(&mut self) {
unsafe { sys::DisposeSBDebugger(self.raw) };
}
}
unsafe impl Send for SBDebugger {}
unsafe impl Sync for SBDebugger {}
pub struct SBDebuggerPlatformIter<'d> {
debugger: &'d SBDebugger,
idx: u32,
}
impl<'d> Iterator for SBDebuggerPlatformIter<'d> {
type Item = SBPlatform;
fn next(&mut self) -> Option<SBPlatform> {
if self.idx < unsafe { sys::SBDebuggerGetNumPlatforms(self.debugger.raw) } {
let r = Some(SBPlatform::wrap(unsafe {
sys::SBDebuggerGetPlatformAtIndex(self.debugger.raw, self.idx)
}));
self.idx += 1;
r
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = unsafe { sys::SBDebuggerGetNumPlatforms(self.debugger.raw) } as usize;
(sz - self.idx as usize, Some(sz))
}
}
impl<'d> ExactSizeIterator for SBDebuggerPlatformIter<'d> {}
pub struct SBDebuggerAvailablePlatformIter<'d> {
debugger: &'d SBDebugger,
idx: u32,
}
impl<'d> Iterator for SBDebuggerAvailablePlatformIter<'d> {
type Item = SBStructuredData;
fn next(&mut self) -> Option<SBStructuredData> {
if self.idx < unsafe { sys::SBDebuggerGetNumAvailablePlatforms(self.debugger.raw) } {
let r = Some(SBStructuredData::wrap(unsafe {
sys::SBDebuggerGetAvailablePlatformInfoAtIndex(self.debugger.raw, self.idx)
}));
self.idx += 1;
r
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = unsafe { sys::SBDebuggerGetNumAvailablePlatforms(self.debugger.raw) } as usize;
(sz - self.idx as usize, Some(sz))
}
}
impl<'d> ExactSizeIterator for SBDebuggerAvailablePlatformIter<'d> {}
#[cfg(feature = "graphql")]
impl ::juniper::Context for SBDebugger {}
#[cfg(feature = "graphql")]
#[graphql_object]
impl SBDebugger {
fn targets() -> Vec<SBTarget> {
self.targets().collect()
}
fn selected_target() -> Option<SBTarget> {
self.selected_target()
}
fn selected_platform() -> SBPlatform {
self.selected_platform()
}
fn platforms() -> Vec<SBPlatform> {
self.platforms().collect()
}
fn available_platforms() -> Vec<SBStructuredData> {
self.available_platforms().collect()
}
}
#[cfg(test)]
mod tests {
use super::SBDebugger;
#[test]
fn it_works() {
assert!(!SBDebugger::version().is_empty());
}
}