use crate::bls::{BLSEntry, KeyValue};
use crate::cmdline::{CmdlineHandler, CmdlineParam};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char};
#[repr(C)]
pub struct CTraitReference {
data: *mut std::os::raw::c_void,
vtable: *mut std::os::raw::c_void
}
fn c_array_to_vector(c_array: *const *const c_char) -> Result<Vec<String>, &'static str> {
let start: *mut usize = c_array as *mut usize;
let mut end: isize = 0;
let mut boxed_address = unsafe { std::ptr::read (start.offset(end))};
while boxed_address != 0 {
boxed_address = unsafe { std::ptr::read (start.offset(end))};
end += 1;
}
end -= 1;
let ptr_slice = unsafe { std::slice::from_raw_parts(c_array, end as usize) };
let vector: Vec<_> = ptr_slice.iter()
.map(|cstr| { unsafe { CStr::from_ptr(*cstr) }})
.map(|cstr| { cstr.to_str() })
.filter_map(|cstr| { match cstr {
Err(_) => None,
Ok(elements) => Some(elements)
}})
.map(|element| { String::from(element) })
.collect();
if vector.len() != end as usize {
return Err("could not convert pointer to vector");
}
Ok(vector)
}
fn generic_cmdline_handler(env: &mut dyn CmdlineHandler, params: *const *const c_char, op: &dyn Fn(&mut dyn CmdlineHandler, &[String]) -> std::io::Result<()>) -> c_char {
let params = match c_array_to_vector(params) {
Ok(params) => params,
Err(_) => { return 0; }
};
match op(env, ¶ms[..]) {
Ok(_) => 1,
Err(_) => 0
}
}
fn generic_cmdline_get (env: &mut dyn CmdlineHandler, param: *const c_char) -> *mut CmdlineParam {
let param = match unsafe { CStr::from_ptr(param) }.to_str() {
Ok(param) => param,
Err(_) => { return std::ptr::null_mut(); }
};
let cmdline = env.cmdline_get(&String::from(param));
match cmdline {
Ok(cmdline) => {
let cmdline = Box::new(cmdline);
Box::into_raw(cmdline)
}
Err(_) => std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_param_foreach (cmdline: *mut CmdlineParam, lambda: extern "C" fn (val: *const c_char, user_data: *mut std::ffi::c_void), user_data: *mut std::ffi::c_void) {
let cmdline = unsafe{ Box::from_raw(cmdline) };
for param_value in cmdline.iter() {
match param_value {
Some(param_value) => {
let c_param_value = CString::new(param_value.as_str()).unwrap();
lambda (c_param_value.as_ptr(), user_data);
}
None => {
lambda (std::ptr::null(), user_data);
}
}
};
Box::into_raw(cmdline);
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_param_get_size (cmdline: *mut CmdlineParam) -> usize {
let cmdline = unsafe{ Box::from_raw(cmdline) };
let size = cmdline.len();
Box::into_raw(cmdline);
size
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_param_destroy(cmdline: *mut CmdlineParam) {
unsafe{ Box::from_raw(cmdline) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_new(entry: *const c_char) -> *mut BLSEntry {
let entry = match unsafe { CStr::from_ptr(entry) }.to_str() {
Ok(entry_name) => String::from(entry_name),
Err(_) => { return std::ptr::null_mut(); }
};
if let Ok(entry) = BLSEntry::new(&entry) {
Box::into_raw(Box::new(entry))
} else {
std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_destroy(entry: *mut BLSEntry) {
unsafe { Box::from_raw(entry) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_get (entry: *mut BLSEntry, key: *const c_char) -> *mut KeyValue {
let entry = unsafe { Box::from_raw(entry) };
let key = match unsafe { CStr::from_ptr(key) }.to_str() {
Ok(key) => key,
_ => { return std::ptr::null_mut(); }
};
match entry.get(key) {
Ok(keyvalue) => {
let keyvalue = Box::new(keyvalue);
Box::into_raw(keyvalue)
},
Err(_) => std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_set (entry: *mut BLSEntry, key: *const c_char,
value: *const *const c_char) -> c_char {
let entry = unsafe { Box::from_raw(entry) };
let key = match unsafe { CStr::from_ptr(key) }.to_str() {
Ok(key) => key,
_ => { return 0; }
};
let value = match c_array_to_vector(value) {
Ok(value) => value,
Err(_) => { return 0; }
};
let ret = match entry.set(key, &value) {
Ok(_) => 1,
_ => 0
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_remove (entry: *mut BLSEntry, key: *const c_char) -> c_char {
let entry = unsafe { Box::from_raw(entry) };
let key = match unsafe { CStr::from_ptr(key) }.to_str() {
Ok(key) => key,
_ => { return 0; }
};
let ret = match entry.remove(key) {
Ok(_) => 1,
_ => 0
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_list () -> *mut Vec<String> {
match BLSEntry::get_bls_entries() {
Ok(entries) => {
Box::into_raw(Box::new(entries))
},
Err(_) => std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_list_destroy(list: *mut Vec<String>) {
let _ = unsafe { Box::from_raw(list) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_to_cmdline (entry: *mut BLSEntry) -> CTraitReference {
let mut entry = unsafe { Box::from_raw(entry) };
let ret: CTraitReference = {
let handler: &mut dyn CmdlineHandler = &mut *entry;
unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_list_to_cmdline (list: *mut Vec<String>) -> CTraitReference {
let mut list = unsafe { Box::from_raw(list) };
let ret: CTraitReference = {
let handler: &mut dyn CmdlineHandler = &mut *list;
unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
};
Box::into_raw(list);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_get (handler: CTraitReference, param: *mut c_char) -> *mut CmdlineParam {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_get (handler, param)
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_set (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_set(p) })
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_add (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_add(p) })
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_remove (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_remove(p) })
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_clear (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_clear(p) })
}