use crate::{sys, SBError, SBStream, SBStringList};
use std::ffi::CString;
use std::fmt;
use std::ptr;
pub struct SBStructuredData {
pub raw: sys::SBStructuredDataRef,
}
impl SBStructuredData {
pub(crate) fn wrap(raw: sys::SBStructuredDataRef) -> SBStructuredData {
SBStructuredData { raw }
}
pub(crate) fn maybe_wrap(raw: sys::SBStructuredDataRef) -> Option<SBStructuredData> {
if unsafe { sys::SBStructuredDataIsValid(raw) } {
Some(SBStructuredData { raw })
} else {
None
}
}
pub fn is_valid(&self) -> bool {
unsafe { sys::SBStructuredDataIsValid(self.raw) }
}
#[allow(missing_docs)]
pub fn clear(&self) {
unsafe { sys::SBStructuredDataClear(self.raw) };
}
#[allow(missing_docs)]
pub fn set_from_json(&self, stream: &SBStream) -> Result<(), SBError> {
let e = SBError::wrap(unsafe { sys::SBStructuredDataSetFromJSON(self.raw, stream.raw) });
if e.is_success() {
Ok(())
} else {
Err(e)
}
}
#[allow(missing_docs)]
pub fn get_as_json(&self) -> Result<SBStream, SBError> {
let stream = SBStream::new();
let e = SBError::wrap(unsafe { sys::SBStructuredDataGetAsJSON(self.raw, stream.raw) });
if e.is_success() {
Ok(stream)
} else {
Err(e)
}
}
pub fn data_type(&self) -> sys::StructuredDataType {
unsafe { sys::SBStructuredDataGetType(self.raw) }
}
pub fn size(&self) -> usize {
unsafe { sys::SBStructuredDataGetSize(self.raw) }
}
pub fn keys(&self) -> SBStringList {
let names = SBStringList::new();
unsafe { sys::SBStructuredDataGetKeys(self.raw, names.raw) };
names
}
pub fn value_for_key(&self, key: &str) -> Option<SBStructuredData> {
let key = CString::new(key).unwrap();
SBStructuredData::maybe_wrap(unsafe {
sys::SBStructuredDataGetValueForKey(self.raw, key.as_ptr())
})
}
pub fn item_at_index(&self, idx: usize) -> Option<SBStructuredData> {
SBStructuredData::maybe_wrap(unsafe { sys::SBStructuredDataGetItemAtIndex(self.raw, idx) })
}
pub fn integer_value(&self) -> Option<u64> {
if self.data_type() == sys::StructuredDataType::Integer {
Some(unsafe { sys::SBStructuredDataGetIntegerValue(self.raw, 0) })
} else {
None
}
}
pub fn float_value(&self) -> Option<f64> {
if self.data_type() == sys::StructuredDataType::Float {
Some(unsafe { sys::SBStructuredDataGetFloatValue(self.raw, 0.0) })
} else {
None
}
}
pub fn boolean_value(&self) -> Option<bool> {
if self.data_type() == sys::StructuredDataType::Boolean {
Some(unsafe { sys::SBStructuredDataGetBooleanValue(self.raw, false) })
} else {
None
}
}
pub fn string_value(&self) -> Option<String> {
if self.data_type() == sys::StructuredDataType::String {
unsafe {
let sz = sys::SBStructuredDataGetStringValue(self.raw, ptr::null_mut(), 0) + 1;
let mut buf: Vec<u8> = Vec::with_capacity(sz);
sys::SBStructuredDataGetStringValue(self.raw, buf.as_mut_ptr() as *mut i8, sz);
buf.set_len(sz);
String::from_utf8(buf).ok()
}
} else {
None
}
}
}
impl Clone for SBStructuredData {
fn clone(&self) -> SBStructuredData {
SBStructuredData {
raw: unsafe { sys::CloneSBStructuredData(self.raw) },
}
}
}
impl fmt::Debug for SBStructuredData {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let stream = SBStream::new();
unsafe { sys::SBStructuredDataGetDescription(self.raw, stream.raw) };
write!(fmt, "SBStructuredData {{ {} }}", stream.data())
}
}
impl Drop for SBStructuredData {
fn drop(&mut self) {
unsafe { sys::DisposeSBStructuredData(self.raw) };
}
}
unsafe impl Send for SBStructuredData {}
unsafe impl Sync for SBStructuredData {}
#[cfg(feature = "graphql")]
#[graphql_object]
impl SBStructuredData {
fn size() -> i32 {
self.size() as i32
}
}