use crate::{
sys, SBFileSpec, SBSection, SBStream, SBSymbol, SBSymbolContextList, SBTypeList, SymbolType,
TypeClass,
};
use std::ffi::CString;
use std::fmt;
pub struct SBModule {
pub raw: sys::SBModuleRef,
}
impl SBModule {
pub(crate) fn wrap(raw: sys::SBModuleRef) -> SBModule {
SBModule { raw }
}
pub(crate) fn maybe_wrap(raw: sys::SBModuleRef) -> Option<SBModule> {
if unsafe { sys::SBModuleIsValid(raw) } {
Some(SBModule { raw })
} else {
None
}
}
pub fn is_valid(&self) -> bool {
unsafe { sys::SBModuleIsValid(self.raw) }
}
pub fn filespec(&self) -> SBFileSpec {
SBFileSpec::wrap(unsafe { sys::SBModuleGetFileSpec(self.raw) })
}
pub fn platform_filespec(&self) -> SBFileSpec {
SBFileSpec::wrap(unsafe { sys::SBModuleGetPlatformFileSpec(self.raw) })
}
#[allow(missing_docs)]
pub fn find_section(&self, name: &str) -> Option<SBSection> {
let name = CString::new(name).unwrap();
SBSection::maybe_wrap(unsafe { sys::SBModuleFindSection(self.raw, name.as_ptr()) })
}
pub fn sections(&self) -> SBModuleSectionIter {
SBModuleSectionIter {
module: self,
idx: 0,
}
}
#[allow(missing_docs)]
pub fn find_functions(&self, name: &str, name_type_mask: u32) -> SBSymbolContextList {
let name = CString::new(name).unwrap();
SBSymbolContextList::wrap(unsafe {
sys::SBModuleFindFunctions(self.raw, name.as_ptr(), name_type_mask)
})
}
#[allow(missing_docs)]
pub fn find_symbols(&self, name: &str, symbol_type: SymbolType) -> SBSymbolContextList {
let name = CString::new(name).unwrap();
SBSymbolContextList::wrap(unsafe {
sys::SBModuleFindSymbols(self.raw, name.as_ptr(), symbol_type)
})
}
pub fn types(&self, type_mask: TypeClass) -> SBTypeList {
SBTypeList::wrap(unsafe { sys::SBModuleGetTypes(self.raw, type_mask.bits()) })
}
pub fn symbols(&self) -> SBModuleSymbolsIter {
SBModuleSymbolsIter {
module: self,
index: 0,
}
}
}
pub struct SBModuleSectionIter<'d> {
module: &'d SBModule,
idx: usize,
}
impl Iterator for SBModuleSectionIter<'_> {
type Item = SBSection;
fn next(&mut self) -> Option<SBSection> {
if self.idx < unsafe { sys::SBModuleGetNumSections(self.module.raw) } {
let r = Some(SBSection::wrap(unsafe {
sys::SBModuleGetSectionAtIndex(self.module.raw, self.idx)
}));
self.idx += 1;
r
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = unsafe { sys::SBModuleGetNumSections(self.module.raw) };
(sz - self.idx, Some(sz))
}
}
impl ExactSizeIterator for SBModuleSectionIter<'_> {}
pub struct SBModuleSymbolsIter<'d> {
module: &'d SBModule,
index: usize,
}
impl Iterator for SBModuleSymbolsIter<'_> {
type Item = SBSymbol;
fn next(&mut self) -> Option<Self::Item> {
self.nth(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = unsafe { sys::SBModuleGetNumSections(self.module.raw) };
let len = size - self.index;
(len, Some(len))
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let size = unsafe { sys::SBModuleGetNumSections(self.module.raw) };
let index = n + self.index;
if index < size {
let symbol = unsafe { sys::SBModuleGetSymbolAtIndex(self.module.raw, index) };
self.index = index + 1;
Some(SBSymbol { raw: symbol })
} else {
self.index = self.len();
None
}
}
}
impl ExactSizeIterator for SBModuleSymbolsIter<'_> {}
impl Clone for SBModule {
fn clone(&self) -> SBModule {
SBModule {
raw: unsafe { sys::CloneSBModule(self.raw) },
}
}
}
impl fmt::Debug for SBModule {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let stream = SBStream::new();
unsafe { sys::SBModuleGetDescription(self.raw, stream.raw) };
write!(fmt, "SBModule {{ {} }}", stream.data())
}
}
impl Drop for SBModule {
fn drop(&mut self) {
unsafe { sys::DisposeSBModule(self.raw) };
}
}
unsafe impl Send for SBModule {}
unsafe impl Sync for SBModule {}
#[cfg(feature = "graphql")]
#[juniper::graphql_object]
impl SBModule {
fn filespec() -> SBFileSpec {
self.filespec()
}
fn platform_filespec() -> SBFileSpec {
self.platform_filespec()
}
fn sections() -> Vec<SBSection> {
self.sections().collect()
}
}