use shared::{func::pxs_Func, var::pxs_Var};
use std::{
cell::Cell,
ffi::{CString, c_char, c_void},
ptr,
sync::Arc,
};
#[cfg(feature = "lua")]
use crate::lua::LuaScripting;
#[cfg(feature = "python")]
use crate::python::PythonScripting;
use crate::shared::{
LoadFileFn, PixelScript, PtrMagic, ReadDirFn, WriteFileFn,
func::{clear_function_lookup, lookup_add_function},
get_pixel_state,
module::pxs_Module,
object::{FreeMethod, clear_object_lookup, lookup_add_object, pxs_PixelObject},
pxs_Opaque, pxs_Runtime,
var::{ObjectMethods, pxs_VarT, pxs_VarType},
};
pub mod shared;
#[cfg(feature = "include-core")]
pub mod core;
#[cfg(feature = "lua")]
pub mod lua;
#[cfg(feature = "python")]
pub mod python;
macro_rules! assert_initiated {
() => {{
unsafe {
assert!(IS_INIT, "Pixel script library is not initialized.");
}
}};
}
static mut IS_INIT: bool = false;
static mut IS_KILLED: bool = false;
#[unsafe(no_mangle)]
pub extern "C" fn pxs_version() -> u32 {
pxs_debug!("pxs_version");
let major = 0;
let minor = 3;
let patch = 5;
(major << 16) | (minor << 8) | patch
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_initialize() {
pxs_debug!("pxs_initialize");
unsafe {
if IS_KILLED {
panic!("Once finalized, PixelScript can not be initalized again.");
}
if !IS_INIT {
with_feature!("lua", {
LuaScripting::start();
});
with_feature!("python", {
PythonScripting::start();
});
}
IS_INIT = true;
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_finalize() {
pxs_debug!("pxs_finalize");
assert_initiated!();
unsafe {
if IS_KILLED {
panic!("Can not finalize the runtime twice.");
}
IS_KILLED = true;
}
clear_function_lookup();
clear_object_lookup();
with_feature!("lua", {
LuaScripting::stop();
});
with_feature!("python", {
PythonScripting::stop();
});
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_exec(
runtime: pxs_Runtime,
code: *const c_char,
file_name: *const c_char,
) -> pxs_VarT {
pxs_debug!("pxs_exec");
assert_initiated!();
if code.is_null() || file_name.is_null() {
return pxs_newstring(create_raw_string!("code or file_name are null"));
}
let rcode = borrow_string!(code);
let rfile_name = borrow_string!(file_name);
if rcode.is_empty() || rfile_name.is_empty() {
return pxs_newstring(create_raw_string!("code or file_name are empty strings"));
}
let res = match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::execute(rcode, rfile_name) }, {
panic!("lua is not enabled");
})
}
pxs_Runtime::pxs_Python => {
with_feature!("python", { PythonScripting::execute(rcode, rfile_name) }, {
panic!("python is not enabled");
})
}
pxs_Runtime::pxs_JavaScript => todo!(),
pxs_Runtime::pxs_PHP => todo!(),
};
if res.is_empty() {
pxs_newnull()
} else {
pxs_newstring(create_raw_string!(res))
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_freestr(string: *mut c_char) {
pxs_debug!("pxs_freestr");
assert_initiated!();
if !string.is_null() {
unsafe {
let _ = CString::from_raw(string);
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newmod(name: *const c_char) -> *mut pxs_Module {
pxs_debug!("pxs_newmod");
assert_initiated!();
if name.is_null() {
return ptr::null_mut();
}
let name_str = borrow_string!(name);
pxs_Module::new(name_str.to_owned()).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_addfunc(module_ptr: *mut pxs_Module, name: *const c_char, func: pxs_Func) {
pxs_debug!("pxs_addfunc");
assert_initiated!();
if module_ptr.is_null() {
return;
}
if name.is_null() {
return;
}
let module = unsafe { pxs_Module::from_borrow(module_ptr) };
let name_str = borrow_string!(name);
let full_name = format!("_{}{}", module.name, name_str);
let idx = lookup_add_function(&full_name, func);
module.add_callback(name_str, &full_name, idx);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_addvar(
module_ptr: *mut pxs_Module,
name: *const c_char,
variable: *mut pxs_Var,
) {
pxs_debug!("pxs_addvar");
assert_initiated!();
if module_ptr.is_null() {
return;
}
if name.is_null() {
return;
}
let module = unsafe { pxs_Module::from_borrow(module_ptr) };
let name_str = borrow_string!(name);
module.add_variable(name_str, variable);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_add_submod(parent_ptr: *mut pxs_Module, child_ptr: *mut pxs_Module) {
pxs_debug!("pxs_add_submod");
assert_initiated!();
if parent_ptr.is_null() || child_ptr.is_null() {
return;
}
let parent = unsafe { pxs_Module::from_borrow(parent_ptr) };
let mut child = pxs_Module::from_raw(child_ptr);
child.name = format!("{}.{}", parent.name, child.name);
parent.add_module(Arc::new(child));
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_addmod(module_ptr: *mut pxs_Module) {
pxs_debug!("pxs_addmod");
assert_initiated!();
if module_ptr.is_null() {
return;
}
let module = Arc::new(pxs_Module::from_raw(module_ptr));
with_feature!("lua", {
LuaScripting::add_module(Arc::clone(&module));
});
with_feature!("python", {
PythonScripting::add_module(Arc::clone(&module));
});
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_freemod(module_ptr: *mut pxs_Module) {
pxs_debug!("pxs_freemod");
assert_initiated!();
if module_ptr.is_null() {
return;
}
let _ = pxs_Module::from_raw(module_ptr);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newobject(
ptr: pxs_Opaque,
free_method: FreeMethod,
type_name: *const c_char,
) -> *mut pxs_PixelObject {
pxs_debug!("pxs_newobject");
assert_initiated!();
if ptr.is_null() || type_name.is_null() {
return ptr::null_mut();
}
let type_name = borrow_string!(type_name);
pxs_PixelObject::new(ptr, free_method, type_name).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_object_addfunc(
object_ptr: *mut pxs_PixelObject,
name: *const c_char,
callback: pxs_Func,
) {
pxs_debug!("pxs_object_addfunc");
assert_initiated!();
if object_ptr.is_null() || name.is_null() {
return;
}
let object_borrow = unsafe { pxs_PixelObject::from_borrow(object_ptr) };
let name_borrow = borrow_string!(name);
let full_name = format!("_{}{}", object_borrow.type_name, name_borrow);
let idx = lookup_add_function(full_name.as_str(), callback);
object_borrow.add_callback(name_borrow, full_name.as_str(), idx, true);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_object_add_reffunc(
object_ptr: *mut pxs_PixelObject,
name: *const c_char,
callback: pxs_Func,
) {
pxs_debug!("pxs_object_addfunc");
assert_initiated!();
if object_ptr.is_null() || name.is_null() {
return;
}
let object_borrow = unsafe { pxs_PixelObject::from_borrow(object_ptr) };
let name_borrow = borrow_string!(name);
let full_name = format!("_{}{}", object_borrow.type_name, name_borrow);
let idx = lookup_add_function(full_name.as_str(), callback);
object_borrow.add_callback(name_borrow, full_name.as_str(), idx, false);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_addobject(
module_ptr: *mut pxs_Module,
name: *const c_char,
object_constructor: pxs_Func,
) {
pxs_debug!("pxs_addobject");
pxs_addfunc(module_ptr, name, object_constructor);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newstring(str: *const c_char) -> *mut pxs_Var {
pxs_debug!("pxs_newstring");
let val = borrow_string!(str);
pxs_Var::new_string(val.to_string().clone()).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newnull() -> *mut pxs_Var {
pxs_debug!("pxs_newnull");
pxs_Var::new_null().into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newhost(pixel_object: *mut pxs_PixelObject) -> *mut pxs_Var {
pxs_debug!("pxs_newhost");
assert_initiated!();
if pixel_object.is_null() {
return ptr::null_mut();
}
let pixel_owned = pxs_PixelObject::from_raw(pixel_object);
let pixel_arc = Arc::new(pixel_owned);
let idx = lookup_add_object(Arc::clone(&pixel_arc));
pxs_Var::new_host_object(idx).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newint(val: i64) -> *mut pxs_Var {
pxs_debug!("pxs_newint");
pxs_Var::new_i64(val).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newuint(val: u64) -> *mut pxs_Var {
pxs_debug!("pxs_newuint");
pxs_Var::new_u64(val).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newbool(val: bool) -> *mut pxs_Var {
pxs_debug!("pxs_newbool");
pxs_Var::new_bool(val).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newfloat(val: f64) -> *mut pxs_Var {
pxs_debug!("pxs_newfloat");
pxs_Var::new_f64(val).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_object_callrt(
runtime: pxs_Runtime,
var: *mut pxs_Var,
method: *const c_char,
args: *mut pxs_Var,
) -> *mut pxs_Var {
pxs_debug!("pxs_object_callrt");
pxs_objectcall(
pxs_Var::new_i64(runtime as i64).into_raw(),
var,
method,
args,
)
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_objectcall(
runtime: *mut pxs_Var,
var: *mut pxs_Var,
method: *const c_char,
args: *mut pxs_Var,
) -> pxs_VarT {
pxs_debug!("pxs_objectcall");
assert_initiated!();
if var.is_null() || method.is_null() || args.is_null() || runtime.is_null() {
return ptr::null_mut();
}
let runtime_borrow = unsafe { pxs_Var::from_borrow(runtime) };
let var_borrow = unsafe { pxs_Var::from_borrow(var) };
let method_borrow = borrow_string!(method);
let args = own_var!(args);
if !args.is_list() {
return ptr::null_mut();
}
let list = args.get_list().unwrap();
let runtime = runtime_borrow.get_i64();
if runtime.is_err() {
return ptr::null_mut();
}
let runtime = pxs_Runtime::from_i64(runtime.unwrap());
if runtime.is_none() {
return ptr::null_mut();
}
let runtime = runtime.unwrap();
if !var_borrow.is_object() {
return ptr::null_mut();
}
let var: Result<pxs_Var, anyhow::Error> = match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!(
"lua",
{ LuaScripting::object_call(var_borrow, method_borrow, list) },
{
return std::ptr::null_mut();
}
)
}
pxs_Runtime::pxs_Python => {
with_feature!(
"python",
{ PythonScripting::object_call(var_borrow, method_borrow, list) },
{
return std::ptr::null_mut();
}
)
}
pxs_Runtime::pxs_JavaScript => todo!(),
_ => todo!(), };
if let Ok(var) = var {
var.into_raw()
} else {
ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_getint(var: *mut pxs_Var) -> i64 {
pxs_debug!("pxs_getint");
if var.is_null() {
return -1;
}
let b_var = unsafe { pxs_Var::from_borrow(var) };
unsafe {
match b_var.tag {
pxs_VarType::pxs_Int64 => b_var.value.i64_val,
pxs_VarType::pxs_UInt64 => b_var.value.u64_val as i64,
pxs_VarType::pxs_Bool => b_var.value.bool_val.into(),
pxs_VarType::pxs_Float64 => b_var.value.f64_val as i64,
_ => -1,
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_getuint(var: *mut pxs_Var) -> u64 {
pxs_debug!("pxs_getuint");
if var.is_null() {
return 0;
}
let b_var = unsafe { pxs_Var::from_borrow(var) };
unsafe {
match b_var.tag {
pxs_VarType::pxs_Int64 => b_var.value.i64_val as u64,
pxs_VarType::pxs_UInt64 => b_var.value.u64_val,
pxs_VarType::pxs_Bool => b_var.value.bool_val.into(),
pxs_VarType::pxs_Float64 => b_var.value.f64_val as u64,
_ => 0,
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_getfloat(var: *mut pxs_Var) -> f64 {
pxs_debug!("pxs_getfloat");
if var.is_null() {
return -1.0;
}
let b_var = unsafe { pxs_Var::from_borrow(var) };
unsafe {
match b_var.tag {
pxs_VarType::pxs_Int64 => b_var.value.i64_val as f64,
pxs_VarType::pxs_UInt64 => b_var.value.u64_val as f64,
pxs_VarType::pxs_Bool => b_var.value.bool_val.into(),
pxs_VarType::pxs_Float64 => b_var.value.f64_val,
_ => 0 as f64,
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_getbool(var: *mut pxs_Var) -> bool {
pxs_debug!("pxs_getbool");
if var.is_null() {
return false;
}
unsafe { pxs_Var::from_borrow(var).get_bool().unwrap() }
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_getstring(var: *mut pxs_Var) -> *mut c_char {
pxs_debug!("pxs_getstring");
if var.is_null() {
return ptr::null_mut();
}
unsafe {
let string = pxs_Var::from_borrow(var).get_string().unwrap();
create_raw_string!(string.clone())
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_varis(var: *mut pxs_Var, var_type: pxs_VarType) -> bool {
pxs_debug!("pxs_varis");
if var.is_null() {
return false;
}
let var_borrow = unsafe { pxs_Var::from_borrow(var) };
var_borrow.tag == var_type
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_set_filereader(func: LoadFileFn) {
pxs_debug!("pxs_set_filereader");
assert_initiated!();
let state = get_pixel_state();
let mut load_file = state.load_file.borrow_mut();
*load_file = Some(func);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_set_filewriter(func: WriteFileFn) {
pxs_debug!("pxs_set_filewriter");
assert_initiated!();
let state = get_pixel_state();
let mut write_file = state.write_file.borrow_mut();
*write_file = Some(func);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_set_dirreader(func: ReadDirFn) {
pxs_debug!("pxs_set_dirreader");
assert_initiated!();
let state = get_pixel_state();
let mut read_dir = state.read_dir.borrow_mut();
*read_dir = Some(func);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_freevar(var: *mut pxs_Var) {
pxs_debug!("pxs_freevar");
assert_initiated!();
if var.is_null() {
return;
}
let _ = pxs_Var::from_raw(var);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_startthread() {
pxs_debug!("pxs_startthread");
assert_initiated!();
with_feature!("lua", {
LuaScripting::start_thread();
});
with_feature!("python", {
PythonScripting::start_thread();
});
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_stopthread() {
pxs_debug!("pxs_stopthread");
assert_initiated!();
with_feature!("lua", {
LuaScripting::stop_thread();
});
with_feature!("python", {
PythonScripting::stop_thread();
});
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_clearstate(gc_collect: bool) {
pxs_debug!("pxs_clearstate");
assert_initiated!();
clear_function_lookup();
clear_object_lookup();
with_feature!("lua", {
LuaScripting::clear_state(gc_collect);
});
with_feature!("python", {
PythonScripting::clear_state(gc_collect);
});
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_call(
runtime: *mut pxs_Var,
method: *const c_char,
args: *mut pxs_Var,
) -> *mut pxs_Var {
pxs_debug!("pxs_call");
assert_initiated!();
if runtime.is_null() || method.is_null() || args.is_null() {
return ptr::null_mut();
}
let runtime_borrow = unsafe { pxs_Runtime::from_var_ptr(runtime) };
let method_borrow = borrow_string!(method);
let args = own_var!(args);
if !args.is_list() {
return ptr::null_mut();
}
let list = args.get_list().unwrap();
if let Some(rt) = runtime_borrow {
let res = match rt {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::call_method(method_borrow, list) }, {
return std::ptr::null_mut();
})
}
pxs_Runtime::pxs_Python => {
with_feature!(
"python",
{ PythonScripting::call_method(method_borrow, list) },
{
return std::ptr::null_mut();
}
)
}
_ => todo!(), };
if let Ok(res) = res {
res.into_raw()
} else {
ptr::null_mut()
}
} else {
ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_tostring(runtime: *mut pxs_Var, var: *mut pxs_Var) -> *mut pxs_Var {
pxs_debug!("pxs_tostring");
assert_initiated!();
if var.is_null() || runtime.is_null() {
return ptr::null_mut();
}
let b_var = unsafe { pxs_Var::from_borrow(var) };
match b_var.tag {
pxs_VarType::pxs_Int64 => {
let val = b_var.get_i64().unwrap();
return pxs_Var::new_string(val.to_string()).into_raw();
}
pxs_VarType::pxs_UInt64 => {
let val = b_var.get_u64().unwrap();
return pxs_Var::new_string(val.to_string()).into_raw();
}
pxs_VarType::pxs_String => {
return pxs_Var::new_string(b_var.get_string().unwrap().clone()).into_raw();
}
pxs_VarType::pxs_Bool => {
return pxs_Var::new_string(b_var.get_bool().unwrap().to_string()).into_raw();
}
pxs_VarType::pxs_Float64 => {
return pxs_Var::new_string(b_var.get_f64().unwrap().to_string()).into_raw();
}
_ => {
}
}
let runtime = unsafe { pxs_Runtime::from_var_ptr(runtime) };
if let Some(runtime) = runtime {
let args = pxs_Var::new_list();
let list = args.get_list().unwrap();
list.add_item(b_var.clone());
let res = match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::call_method("tostring", list) }, {
return std::ptr::null_mut();
})
}
pxs_Runtime::pxs_Python => {
with_feature!("python", { PythonScripting::call_method("str", list) }, {
return std::ptr::null_mut();
})
}
pxs_Runtime::pxs_JavaScript => todo!(),
_ => todo!(),
};
if let Ok(res) = res {
res.into_raw()
} else {
ptr::null_mut()
}
} else {
ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newlist() -> *mut pxs_Var {
pxs_debug!("pxs_newlist");
assert_initiated!();
pxs_Var::new_list().into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_listadd(list: *mut pxs_Var, item: *mut pxs_Var) -> i32 {
pxs_debug!("pxs_listadd");
assert_initiated!();
if list.is_null() || item.is_null() {
return -1;
}
let borrow_list = unsafe { pxs_Var::from_borrow(list) };
if !borrow_list.is_list() {
return -1;
}
let owned_item = pxs_Var::from_raw(item);
let varlist = borrow_list.get_list().unwrap();
varlist.add_item(owned_item);
(varlist.vars.len() - 1) as i32
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_listget(list: *mut pxs_Var, index: i32) -> *mut pxs_Var {
pxs_debug!("pxs_listget");
assert_initiated!();
if list.is_null() {
return ptr::null_mut();
}
let borrow_list = unsafe { pxs_Var::from_borrow(list) };
if !borrow_list.is_list() {
return ptr::null_mut();
}
let varlist = borrow_list.get_list().unwrap();
if let Some(res) = varlist.get_item(index) {
res as *const pxs_Var as *mut pxs_Var
} else {
ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_listset(list: *mut pxs_Var, index: i32, item: *mut pxs_Var) -> bool {
pxs_debug!("pxs_listset");
assert_initiated!();
if list.is_null() || item.is_null() {
return false;
}
let borrow_list = unsafe { pxs_Var::from_borrow(list) };
if !borrow_list.is_list() {
return false;
}
let list = borrow_list.get_list().unwrap();
let owned_item = pxs_Var::from_raw(item);
list.set_item(owned_item, index)
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_listlen(list: *mut pxs_Var) -> i32 {
pxs_debug!("pxs_listlen");
assert_initiated!();
if list.is_null() {
return -1;
}
let borrow_list = unsafe { pxs_Var::from_borrow(list) };
if !borrow_list.is_list() {
return -1;
}
let list = borrow_list.get_list().unwrap();
list.vars.len() as i32
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_varcall(
runtime: *mut pxs_Var,
var_func: *mut pxs_Var,
args: *mut pxs_Var,
) -> *mut pxs_Var {
pxs_debug!("pxs_varcall");
assert_initiated!();
if runtime.is_null() || var_func.is_null() || args.is_null() {
return ptr::null_mut();
}
let borrow_func = borrow_var!(var_func);
if !borrow_func.is_function() {
return ptr::null_mut();
}
let args = own_var!(args);
if !args.is_list() {
return ptr::null_mut();
}
let list = args.get_list().unwrap();
let runtime = unsafe { pxs_Runtime::from_var_ptr(runtime) };
if let Some(runtime) = runtime {
match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!(
"lua",
{ LuaScripting::var_call(borrow_func, list).unwrap() },
{
return std::ptr::null_mut();
}
)
}
pxs_Runtime::pxs_Python => {
with_feature!(
"python",
{ PythonScripting::var_call(borrow_func, list).unwrap() },
{
return std::ptr::null_mut();
}
)
}
pxs_Runtime::pxs_JavaScript => todo!(),
_ => todo!(), }
.into_raw()
} else {
ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newcopy(item: *mut pxs_Var) -> *mut pxs_Var {
pxs_debug!("pxs_newcopy");
assert_initiated!();
if item.is_null() {
return ptr::null_mut();
}
let borrow_item = borrow_var!(item);
let cloned_var = borrow_item.clone();
cloned_var.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_objectget(runtime: pxs_VarT, obj: pxs_VarT, key: *const c_char) -> pxs_VarT {
pxs_debug!("pxs_objectget");
assert_initiated!();
if runtime.is_null() || obj.is_null() || key.is_null() {
return ptr::null_mut();
}
let borrow_obj = borrow_var!(obj);
let borrow_rt = unsafe { pxs_Runtime::from_var_ptr(runtime).unwrap() };
let borrow_key = borrow_string!(key);
let res = match borrow_rt {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::get(borrow_obj, borrow_key) }, {
return ptr::null_mut();
})
}
pxs_Runtime::pxs_Python => {
with_feature!(
"python",
{ PythonScripting::get(borrow_obj, borrow_key) },
{
return ptr::null_mut();
}
)
}
_ => todo!(), };
match res {
Ok(t) => t.into_raw(),
Err(_) => ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_objectset(
runtime: pxs_VarT,
obj: pxs_VarT,
key: *const c_char,
value: pxs_VarT,
) -> bool {
pxs_debug!("pxs_objectset");
assert_initiated!();
if runtime.is_null() || obj.is_null() || key.is_null() || value.is_null() {
return false;
}
let rt = unsafe { pxs_Runtime::from_var_ptr(runtime).unwrap() };
let borrow_obj = borrow_var!(obj);
let borrow_key = borrow_string!(key);
let owned_value = own_var!(value);
let res = match rt {
pxs_Runtime::pxs_Lua => {
with_feature!(
"lua",
{ LuaScripting::set(borrow_obj, borrow_key, &owned_value) },
{
return false;
}
)
}
pxs_Runtime::pxs_Python => {
with_feature!(
"python",
{ PythonScripting::set(borrow_obj, borrow_key, &owned_value) },
{
return false;
}
)
}
_ => todo!(),
};
match res {
Ok(v) => v.get_bool().unwrap(),
Err(_) => false,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_eval(script: *const c_char, rt: pxs_Runtime) -> pxs_VarT {
pxs_debug!("pxs_eval");
if script.is_null() {
return pxs_newnull();
}
let script = borrow_string!(script);
match rt {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::eval(script).into_raw() }, {
pxs_newnull()
})
}
pxs_Runtime::pxs_Python => {
with_feature!("python", { PythonScripting::eval(script).into_raw() }, {
pxs_newnull()
})
}
pxs_Runtime::pxs_JavaScript => todo!(),
pxs_Runtime::pxs_PHP => todo!(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newfactory(func: pxs_Func, args: *mut pxs_Var) -> pxs_VarT {
pxs_debug!("pxs_newfactory");
assert_initiated!();
if args.is_null() {
return ptr::null_mut();
}
let borrow_args = unsafe { pxs_Var::from_borrow(args) };
if !borrow_args.is_list() {
return ptr::null_mut();
}
pxs_Var::new_factory(func, args).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_gethost(runtime: pxs_VarT, var: pxs_VarT) -> *mut c_void {
pxs_debug!("pxs_gethost");
assert_initiated!();
if runtime.is_null() || var.is_null() {
return ptr::null_mut();
}
let borrow_var = unsafe { pxs_Var::from_borrow(var) };
if borrow_var.is_object() {
let key = create_raw_string!("_pxs_ptr");
let idx_var = pxs_objectget(runtime, var, key);
unsafe {
free_raw_string!(key);
}
if idx_var.is_null() {
return ptr::null_mut();
}
let idx_own = pxs_Var::from_raw(idx_var);
idx_own.get_host_ptr()
} else if borrow_var.is_i64() || borrow_var.is_u64() || borrow_var.is_host_object() {
borrow_var.get_host_ptr()
} else if borrow_var.is_factory() {
let factory = borrow_var.get_factory().unwrap();
let res = factory.call(unsafe { pxs_Runtime::from_var_ptr(runtime) }.unwrap());
let res_raw = res.into_raw();
let host = pxs_gethost(runtime, res_raw);
let _ = pxs_Var::from_raw(res_raw);
host
} else {
ptr::null_mut()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_debugvar(var: pxs_VarT) -> *mut c_char {
pxs_debug!("pxs_debugvar");
if var.is_null() {
create_raw_string!("NULL")
} else {
let borrow_var = unsafe { pxs_Var::from_borrow(var) };
let str = format!("{:#?}", borrow_var);
create_raw_string!(str)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newexception(msg: *const c_char) -> pxs_VarT {
pxs_debug!("pxs_newexception");
if msg.is_null() {
return std::ptr::null_mut();
}
let bmsg = borrow_string!(msg);
pxs_Var::new_exception(bmsg.to_string().clone()).into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_var_fromname(rt: pxs_VarT, name: *const c_char) -> pxs_VarT {
pxs_debug!("pxs_var_fromname");
assert_initiated!();
if name.is_null() {
return pxs_Var::new_null().into_raw();
}
let bname = borrow_string!(name);
let runtime = unsafe { pxs_Runtime::from_var_ptr(rt) };
if let Some(runtime) = runtime {
match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!(
"lua",
{ LuaScripting::get_from_name(bname).unwrap_or(pxs_Var::new_null()) },
{ pxs_Var::new_null() }
)
}
pxs_Runtime::pxs_Python => {
with_feature!(
"python",
{ PythonScripting::get_from_name(bname).unwrap_or(pxs_Var::new_null()) },
{ pxs_Var::new_null() }
)
}
pxs_Runtime::pxs_JavaScript => todo!(),
pxs_Runtime::pxs_PHP => todo!(),
}
.into_raw()
} else {
pxs_Var::new_null().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_listdel(list: pxs_VarT, index: i32) -> bool {
pxs_debug!("pxs_listdel");
if list.is_null() {
return false;
}
let var = borrow_var!(list);
if !var.is_list() {
return false;
}
let var_list = var.get_list().unwrap();
var_list.del_item(index)
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_new_shallowcopy(var: pxs_VarT) -> pxs_VarT {
pxs_debug!("pxs_new_shallowcopy");
if var.is_null() {
return pxs_newnull();
}
let bvar = borrow_var!(var);
bvar.shallow_copy().into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_compile(
runtime: pxs_Runtime,
code: *const c_char,
global_scope: pxs_VarT,
) -> pxs_VarT {
pxs_debug!("pxs_compile");
assert_initiated!();
if code.is_null() || global_scope.is_null() {
return pxs_newnull();
}
let rcode = borrow_string!(code);
let scope = own_var!(global_scope);
if !scope.is_map() && !scope.is_null() {
return pxs_Var::new_exception("Global scope must be a Map or Null".to_string()).into_raw();
}
let res = match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::compile(rcode, scope) }, {
panic!("lua feature is not enabled")
})
}
pxs_Runtime::pxs_Python => {
with_feature!("python", { PythonScripting::compile(rcode, scope) }, {
panic!("python feature is not enabled")
})
}
pxs_Runtime::pxs_JavaScript => todo!(),
pxs_Runtime::pxs_PHP => todo!(),
};
if !res.is_list() {
return res.into_raw();
}
let list = res.get_list().unwrap();
list.insert_item(0, unsafe { runtime.into_var() });
res.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_execobject(object: pxs_VarT, local: pxs_VarT) -> pxs_VarT {
pxs_debug!("pxs_execobject");
assert_initiated!();
if object.is_null() || local.is_null() {
return pxs_newnull();
}
let var = own_var!(object);
if !var.is_list() {
return pxs_Var::new_exception("Compiled object is not the correct type.").into_raw();
}
let scope = own_var!(local);
if !scope.is_map() && !scope.is_null() {
return pxs_Var::new_exception("Scope must be a Map or Null.").into_raw();
}
let list = var.get_list().unwrap();
let rt = list.get_item(0);
if let Some(rt) = rt {
let runtime = pxs_Runtime::from_var(rt);
if let Some(runtime) = runtime {
return match runtime {
pxs_Runtime::pxs_Lua => {
with_feature!("lua", { LuaScripting::exec_object(var, scope) }, {
panic!("lua feature not enabled")
})
}
pxs_Runtime::pxs_Python => {
with_feature!("python", { PythonScripting::exec_object(var, scope) }, {
panic!("python feature not enabled")
})
}
pxs_Runtime::pxs_JavaScript => todo!(),
pxs_Runtime::pxs_PHP => todo!(),
}
.into_raw();
} else {
panic!("Not a valid runtime supplied.");
}
} else {
panic!("List supplied is empty.");
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_newmap() -> pxs_VarT {
pxs_debug!("pxs_newmap");
pxs_Var::new_map().into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_map_addpair(map: pxs_VarT, key: pxs_VarT, value: pxs_VarT) {
pxs_debug!("pxs_map_addpair");
if map.is_null() || key.is_null() || value.is_null() {
return;
}
let map = borrow_var!(map);
if !map.is_map() {
return;
}
let key = own_var!(key);
if key.is_string() || key.is_i64() || key.is_bool() || key.is_u64() || key.is_f64() {
let internal = map.get_map().unwrap();
internal.add_item(key, own_var!(value));
} else {
return;
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_map_delitem(map: pxs_VarT, key: pxs_VarT) {
pxs_debug!("pxs_map_delitem");
if map.is_null() || key.is_null() {
return;
}
let map = borrow_var!(map);
if !map.is_map() {
return;
}
let key = borrow_var!(key);
let internal = map.get_map().unwrap();
internal.del_item(key);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_maplen(map: pxs_VarT) -> i32 {
pxs_debug!("pxs_maplen");
if map.is_null() {
return -1;
}
let bvar = borrow_var!(map);
if bvar.is_map() {
bvar.get_map().unwrap().len() as i32
} else {
-1
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_mapkeys(map: pxs_VarT) -> pxs_VarT {
pxs_debug!("pxs_mapkeys");
if map.is_null() {
return pxs_newnull();
}
let map = borrow_var!(map);
if !map.is_map() {
return pxs_newnull();
}
let internals = map.get_map().unwrap();
let result = pxs_Var::new_list();
let list = result.get_list().unwrap();
let keys = internals.keys();
for k in keys {
list.add_item(k.clone());
}
result.into_raw()
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_mapget(map: pxs_VarT, key: pxs_VarT) -> pxs_VarT {
pxs_debug!("pxs_mapget");
if map.is_null() || key.is_null() {
return pxs_newnull();
}
let map = borrow_var!(map);
if !map.is_map() {
return pxs_newnull();
}
let internal = map.get_map().unwrap();
let res = internal.get_item(borrow_var!(key));
if let Some(res) = res {
res as *const pxs_Var as *mut pxs_Var
} else {
pxs_newnull()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_listinsert(list: pxs_VarT, index: usize, item: pxs_VarT) {
pxs_debug!("pxs_listinsert");
if list.is_null() || item.is_null() {
return;
}
let list = borrow_var!(list);
if !list.is_list() {
return;
}
let item = own_var!(item);
let internal = list.get_list().unwrap();
internal.insert_item(index, item);
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_json_encode(rt: pxs_VarT, args: pxs_VarT) -> pxs_VarT {
pxs_debug!("pxs_json_encode");
assert_initiated!();
with_feature!(
"pxs_json",
{
unsafe {
if !core::is_valid_pxs_function(rt, args) {
return pxs_newnull();
}
}
core::pxs_json::encode(rt, args)
},
{
panic!("pxs_json feature not enabled.");
}
)
}
#[unsafe(no_mangle)]
pub extern "C" fn pxs_json_decode(rt: pxs_VarT, args: pxs_VarT) -> pxs_VarT {
pxs_debug!("pxs_json_decode");
assert_initiated!();
with_feature!(
"pxs_json",
{
unsafe {
if !core::is_valid_pxs_function(rt, args) {
return pxs_newnull();
}
}
core::pxs_json::decode(rt, args)
},
{
panic!("pxs_json feature not enabled");
}
)
}