#![feature(libc)]
extern crate libc;
use libc::{c_void,c_char};
use std::ffi::{CString,CStr};
use std::ptr;
use std::error::Error;
use std::mem;
#[repr(C,packed)]
pub struct IvyClientPtr {
next: *mut IvyClientPtr,
}
#[repr(C,packed)]
pub struct MsgRcvPtr {
next: *mut MsgRcvPtr,
}
pub enum IvyApplicationEvent {
IvyApplicationConnected,
IvyApplicationDisconnected,
IvyApplicationCongestion,
IvyApplicationDecongestion,
IvyApplicationFifoFull,
}
#[link(name = "ivy")]
extern {
fn IvyInit(app_name: *const c_char, ready_msg: *const c_char, callback: *const c_void, app_data: *const c_void, die_callback: *const c_void, die_data: *const c_void);
fn IvyStart(bus_addr: *const c_char);
fn IvyStop();
fn IvyMainLoop();
fn IvySendMsg(fmt_message: *const c_char, ...);
fn IvyBindMsg(callback: extern fn(app: IvyClientPtr, user_data: *mut c_void, argc: i32, argv: *const *const c_char),
user_data: *const c_void, regexpr: *const c_char, ...) -> MsgRcvPtr;
fn IvyUnbindMsg(id: MsgRcvPtr);
fn IvyChangeMsg (msg: MsgRcvPtr, fmt_regex: *const c_char, ... ) -> MsgRcvPtr;
}
pub fn ivy_init(app_name: String, ready_msg: String) {
let app_name = CString::new(app_name).unwrap();
let ready_msg = CString::new(ready_msg).unwrap();
unsafe {
IvyInit(app_name.as_ptr(), ready_msg.as_ptr(), ptr::null(), ptr::null(), ptr::null(), ptr::null());
}
}
pub fn ivy_start(bus_addr: Option<String>) {
match bus_addr {
Some(addr) => {
unsafe {
IvyStart(CString::new(addr).unwrap().as_ptr());
}
},
None => {
unsafe {
IvyStart(CString::new("").unwrap().as_ptr());
}
}
}
}
pub fn ivy_stop() {
unsafe {
IvyStop();
}
}
pub fn ivy_main_loop() -> Result<(), Box<Error>> {
unsafe {
IvyMainLoop();
}
Ok(())
}
pub fn ivy_send_msg(msg: String) {
let msg = CString::new(msg).unwrap();
unsafe {
IvySendMsg(msg.as_ptr());
}
}
pub fn ivy_bind_msg<F>(cb: F, regexpr: String) -> MsgRcvPtr
where F: Fn(Vec<String>)
{
let regexpr = CString::new(regexpr).unwrap();
let boxed_cb: Box<Box<Fn(Vec<String>)>> = Box::new(Box::new(cb));
unsafe {
IvyBindMsg(apply_closure, Box::into_raw(boxed_cb) as *const c_void, regexpr.as_ptr())
}
}
pub fn ivy_unbind_msg(id: MsgRcvPtr) {
unsafe {
IvyUnbindMsg(id);
}
}
pub fn ivy_change_msg(id: MsgRcvPtr, regexpr: String) -> MsgRcvPtr {
let regexpr = CString::new(regexpr).unwrap();
unsafe {
IvyChangeMsg(id, regexpr.as_ptr())
}
}
extern "C" fn apply_closure(_app: IvyClientPtr, user_data: *mut c_void, argc: i32, argv: *const *const c_char) {
let mut v: Vec<String> = vec![];
for i in 0..argc as isize {
unsafe {
let ptr = argv.offset(i);
v.push(String::from(CStr::from_ptr(*ptr).to_str().unwrap()));
}
}
let closure: &mut Box<Fn(Vec<String>) -> ()> = unsafe { mem::transmute(user_data) };
closure(v);
}