use std::ffi::{c_char, CStr, CString};
use crate::core::{Row, YAD};
use crate::{deserialize, serialize};
#[unsafe(no_mangle)]
pub extern "C" fn yad_new() -> *mut YAD {
Box::into_raw(Box::new(YAD::new()))
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_free(yad: *mut YAD) {
if !yad.is_null() {
unsafe { let _ = Box::from_raw(yad); }
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_version(yad: *mut YAD) -> *const u8 {
if yad.is_null() {
return [0,0,0,1].as_ptr()
}
unsafe {
(&*yad).version.serialize()[1..].as_ptr()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_rows_len(yad: *mut YAD) -> usize {
if yad.is_null() {
return 0
}
unsafe {
(&*yad).rows.len()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_insert_row(yad: *mut YAD, to_insert: *mut Row) -> bool {
if yad.is_null() || to_insert.is_null() {
return false;
}
unsafe {
let yad_ref = &mut *yad;
let map = &mut yad_ref.rows;
let insert_this: Box<Row> = Box::from_raw(to_insert);
map.insert(insert_this.name.clone(), *insert_this);
true
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_remove_row(yad: *mut YAD, name: *const c_char) -> bool {
if yad.is_null() || name.is_null() {
return false;
}
unsafe {
let yad_ref = &mut *yad;
let map = &mut yad_ref.rows;
let c_str = match CStr::from_ptr(name).to_str() {
Ok(s) => s,
Err(_) => return false,
};
map.remove(c_str);
true
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_get_row(yad: *mut YAD, name: *const c_char) -> *mut Row {
if yad.is_null() || name.is_null() {
return std::ptr::null_mut();
}
unsafe {
let yad_ref = &mut *yad;
let map = &mut yad_ref.rows;
let c_str = match CStr::from_ptr(name).to_str() {
Ok(s) => s,
Err(_) => return std::ptr::null_mut(),
};
if let Some(row) = map.get_mut(c_str) {
row as *mut Row
} else {
std::ptr::null_mut()
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_rows_names(yad: *mut YAD) -> *mut *const c_char {
if yad.is_null() {
return std::ptr::null_mut();
}
unsafe {
let yad_ref = &*yad;
let mut raw_ptrs: Vec<*const c_char> = Vec::with_capacity(yad_ref.rows.len());
for (row_name, _) in &yad_ref.rows {
let cstring = CString::new(row_name.as_str()).unwrap();
raw_ptrs.push(cstring.into_raw());
}
let boxed_slice = raw_ptrs.into_boxed_slice();
Box::into_raw(boxed_slice) as *mut *const c_char
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_rows_names_free(names: *mut *const c_char, len: usize) {
if names.is_null() {
return;
}
unsafe {
let slice = std::slice::from_raw_parts_mut(names as *mut *mut c_char, len);
for &mut ptr in slice.as_mut() {
if !ptr.is_null() {
let _ = CString::from_raw(ptr);
}
}
let _ = Box::from_raw(slice as *mut [_] as *mut *mut c_char);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_as_buffer(yad: *mut YAD) -> *const u8 {
if yad.is_null() {
return std::ptr::null();
}
unsafe {
match serialize(&*yad) {
Ok(buff) => {
let boxed = buff.into_boxed_slice();
let ptr = boxed.as_ptr();
std::mem::forget(boxed);
ptr
}
Err(_) => std::ptr::null(),
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn yad_from_buffer(buff: *const u8, len: usize) -> *mut YAD {
if buff.is_null() || len == 0 {
return std::ptr::null_mut();
}
unsafe {
let slice = std::slice::from_raw_parts(buff, len);
let vec = slice.to_vec();
match deserialize(vec) {
Ok(yad) => Box::into_raw(Box::new(yad)),
Err(_) => std::ptr::null_mut(),
}
}
}