use koicore::command::Command;
use std::ffi::{c_char, CStr};
use std::slice;
use std::ptr;
#[repr(C)]
pub struct KoiCommand {
_data: (),
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_GetName(
command: *mut KoiCommand,
buffer: *mut c_char,
buffer_size: usize,
) -> usize {
if command.is_null() {
return 0;
}
let command = unsafe { &*(command as *mut Command) };
let name = command.name();
let name_bytes = name.as_bytes();
let name_len = name_bytes.len();
let required_size = name_len + 1;
if buffer.is_null() || buffer_size < required_size {
return required_size;
}
let buffer_slice = unsafe { slice::from_raw_parts_mut(buffer as *mut u8, buffer_size) };
buffer_slice[..name_len].copy_from_slice(name_bytes);
buffer_slice[name_len] = 0;
required_size
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_GetNameLen(command: *mut KoiCommand) -> usize {
if command.is_null() {
return 0;
}
let command = unsafe { &*(command as *mut Command) };
command.name().len() + 1 }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_New(
name: *const c_char,
) -> *mut KoiCommand {
if name.is_null() {
return ptr::null_mut();
}
let name_str = match unsafe { CStr::from_ptr(name) }.to_str() {
Ok(s) => s.to_string(),
Err(_) => return ptr::null_mut(),
};
let command = Command::new(name_str, Vec::new());
Box::into_raw(Box::new(command)) as *mut KoiCommand
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_NewText(content: *const c_char) -> *mut KoiCommand {
if content.is_null() {
return ptr::null_mut();
}
let content_str = match unsafe { CStr::from_ptr(content) }.to_str() {
Ok(s) => s.to_string(),
Err(_) => return ptr::null_mut(),
};
let command = Command::new_text(content_str);
Box::into_raw(Box::new(command)) as *mut KoiCommand
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_NewAnnotation(content: *const c_char) -> *mut KoiCommand {
if content.is_null() {
return ptr::null_mut();
}
let content_str = match unsafe { CStr::from_ptr(content) }.to_str() {
Ok(s) => s.to_string(),
Err(_) => return ptr::null_mut(),
};
let command = Command::new_annotation(content_str);
Box::into_raw(Box::new(command)) as *mut KoiCommand
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_NewNumber(
value: i64,
) -> *mut KoiCommand {
let command = Command::new_number(value, Vec::new());
Box::into_raw(Box::new(command)) as *mut KoiCommand
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_Del(command: *mut KoiCommand) {
if !command.is_null() {
drop(unsafe { Box::from_raw(command as *mut Command) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_SetName(
command: *mut KoiCommand,
name: *const c_char,
) -> i32 {
if command.is_null() || name.is_null() {
return -1;
}
let name_str = match unsafe { CStr::from_ptr(name) }.to_str() {
Ok(s) => s.to_string(),
Err(_) => return -1,
};
let command = unsafe { &mut *(command as *mut Command) };
command.name = name_str;
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_Clone(command: *const KoiCommand) -> *mut KoiCommand {
if command.is_null() {
return ptr::null_mut();
}
let command = unsafe { &*(command as *const Command) };
let cloned = command.clone();
Box::into_raw(Box::new(cloned)) as *mut KoiCommand
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn KoiCommand_Compare(
command1: *const KoiCommand,
command2: *const KoiCommand,
) -> i32 {
if command1.is_null() || command2.is_null() {
return 0;
}
let cmd1 = unsafe { &*(command1 as *const Command) };
let cmd2 = unsafe { &*(command2 as *const Command) };
(cmd1 == cmd2) as i32
}