use std::ffi::{c_char, c_void, CString};
use crate::bindings::*;
use aes_types::{TaggedData, ES_ERR_OK};
#[derive(Clone, Copy)]
pub struct ServerInterface<'a> {
interface: &'a SoServerInterface,
server: SoHServer,
}
impl<'a> ServerInterface<'a> {
pub fn new(interface: &'a SoServerInterface, server: SoHServer) -> Self {
Self { interface, server }
}
pub fn server(&self) -> SoHServer {
self.server
}
pub fn raw_interface(&self) -> *const SoServerInterface {
self.interface as *const _
}
pub fn dump_object(&self, h_object: SoHObject) -> ESerror_t {
unsafe { (self.interface.dumpObject)(h_object) }
}
pub fn dump_server(&self) -> ESerror_t {
unsafe { (self.interface.dumpServer)(self.server) }
}
pub fn get_live_object(&self, h_object: SoHObject, name: &str) -> Result<TaggedData, ESerror_t> {
unsafe {
let c_name = CString::new(name).unwrap();
let mut value = TaggedData::new_undefined();
let result = (self.interface.getLiveObject)(
self.server,
h_object,
c_name.as_ptr() as *mut c_char,
&mut value
);
if result == ES_ERR_OK {
Ok(value)
} else {
Err(result)
}
}
}
pub fn get_live_object_from_raw_address(&self, h_object: SoHObject, address: *mut c_void) -> Result<TaggedData, ESerror_t> {
unsafe {
let mut value = TaggedData::new_undefined();
let result = (self.interface.getLiveObject)(
self.server,
h_object,
address as *mut c_char,
&mut value
);
if result == ES_ERR_OK {
Ok(value)
} else {
Err(result)
}
}
}
pub fn put_live_object(&self, h_object: SoHObject, name: &str, value: &TaggedData) -> ESerror_t {
unsafe {
let c_name = CString::new(name).unwrap();
(self.interface.putLiveObject)(
self.server,
h_object,
c_name.as_ptr() as *mut c_char,
value as *const _ as *mut _
)
}
}
pub fn call_live_object(&self, h_object: SoHObject, method: &str, args: &[TaggedData]) -> Result<TaggedData, ESerror_t> {
unsafe {
let c_method = CString::new(method).unwrap();
let mut result = TaggedData::new_undefined();
let error = (self.interface.callLiveObject)(
self.server,
h_object,
c_method.as_ptr() as *mut c_char,
args.len() as i32,
args.as_ptr() as *mut _,
&mut result
);
if error == ES_ERR_OK {
Ok(result)
} else {
Err(error)
}
}
}
pub fn eval(&self, script: &str) -> Result<TaggedData, ESerror_t> {
unsafe {
let c_script = CString::new(script).unwrap();
let mut result = TaggedData::new_undefined();
let error = (self.interface.eval)(
self.server,
c_script.into_raw(),
&mut result
);
if error == ES_ERR_OK {
Ok(result)
} else {
Err(error)
}
}
}
pub fn tagged_data_init(&self) -> Result<TaggedData, ESerror_t> {
unsafe {
let mut data = TaggedData::new_undefined();
let result = (self.interface.taggedDataInit)(self.server, &mut data);
if result == ES_ERR_OK {
Ok(data)
} else {
Err(result)
}
}
}
pub fn tagged_data_free(&self, data: &mut TaggedData) {
unsafe {
let _ = (self.interface.taggedDataFree)(self.server, data);
}
}
pub fn add_class(&self, name: &str, object_interface: &mut SoObjectInterface) -> ESerror_t {
unsafe {
let c_name = CString::new(name).unwrap();
(self.interface.addClass)(
self.server,
c_name.as_ptr() as *mut c_char,
object_interface as *mut _
)
}
}
pub fn add_method(&self, h_object: SoHObject, name: &str, id: i32, desc: &str) -> ESerror_t {
unsafe {
let c_name = CString::new(name).unwrap();
let c_desc = CString::new(desc).unwrap();
(self.interface.addMethod)(
h_object,
c_name.as_ptr(),
id,
c_desc.as_ptr() as *mut c_char
)
}
}
pub fn add_methods(&self, h_object: SoHObject, names: &mut [SoCClientName]) -> ESerror_t {
unsafe {
(self.interface.addMethods)(
h_object,
names.as_mut_ptr()
)
}
}
pub fn add_property(&self, h_object: SoHObject, name: &str, id: i32, desc: &str) -> ESerror_t {
unsafe {
let c_name = CString::new(name).unwrap();
let c_desc = CString::new(desc).unwrap();
(self.interface.addProperty)(
h_object,
c_name.as_ptr(),
id,
c_desc.as_ptr() as *mut c_char
)
}
}
pub fn add_properties(&self, h_object: SoHObject, names: &mut [SoCClientName]) -> ESerror_t {
unsafe {
(self.interface.addProperties)(
h_object,
names.as_mut_ptr()
)
}
}
pub fn get_class(&self, h_object: SoHObject, max_name_len: i32) -> Result<String, ESerror_t> {
unsafe {
let mut buffer = vec![0u8; max_name_len as usize];
let result = (self.interface.getClass)(
h_object,
buffer.as_mut_ptr() as *mut c_char,
max_name_len
);
if result == ES_ERR_OK {
Ok(String::from_utf8_lossy(&buffer).trim_matches(char::from(0)).to_string())
} else {
Err(result)
}
}
}
pub fn get_server(&self, h_object: SoHObject) -> Result<(SoHServer, &'a SoServerInterface), ESerror_t> {
unsafe {
let mut server = std::ptr::null_mut();
let mut interface = std::ptr::null_mut();
let result = (self.interface.getServer)(
h_object,
&mut server,
&mut interface
);
if result == ES_ERR_OK {
Ok((server, &*interface))
} else {
Err(result)
}
}
}
pub fn set_client_data(&self, h_object: SoHObject, client_data: *mut c_void) -> ESerror_t {
unsafe {
(self.interface.setClientData)(h_object, client_data)
}
}
pub fn get_client_data<T>(&self, h_object: SoHObject) -> Result<*mut T, ESerror_t> {
unsafe {
let mut client_data: *mut c_void = std::ptr::null_mut();
let result = (self.interface.getClientData)(h_object, &mut client_data);
if result == ES_ERR_OK {
Ok(client_data as *mut T)
} else {
Err(result)
}
}
}
}
#[macro_export]
macro_rules! with_server_interface {
($retval:expr, |$interface:ident| $body:expr) => {
match { CLIENT_DATA.as_ref().and_then(|data| data.server_interface.as_ref()) } {
Some(raw_interface) => {
let $interface = ServerInterface::new(raw_interface, get_server!($retval));
$body
},
None => return make_error_result(ES_ERR_NO_MEMORY, $retval)
}
};
}