use bitflags::bitflags;
use crate::ctx::DukContext;
use super::*;
bitflags! {
pub struct DukCompileFlags: u32 {
const DUK_COMPILE_EVAL = (1 << 3);
const DUK_COMPILE_FUNCTION = (1 << 4);
const DUK_COMPILE_STRICT = (1 << 5);
const DUK_COMPILE_SHEBANG = (1 << 6);
const DUK_COMPILE_SAFE = (1 << 7);
const DUK_COMPILE_NORESULT = (1 << 8);
const DUK_COMPILE_NOSOURCE = (1 << 9);
const DUK_COMPILE_STRLEN = (1 << 10);
const DUK_COMPILE_NOFILENAME = (1 << 11);
const DUK_COMPILE_FUNCEXPR = (1 << 12);
}
}
bitflags! {
pub struct DukDefpropFlags: u32 {
const DUK_DEFPROP_WRITABLE = (1 << 0);
const DUK_DEFPROP_ENUMERABLE = (1 << 1);
const DUK_DEFPROP_CONFIGURABLE = (1 << 2);
const DUK_DEFPROP_HAVE_WRITABLE = (1 << 3);
const DUK_DEFPROP_HAVE_ENUMERABLE = (1 << 4);
const DUK_DEFPROP_HAVE_CONFIGURABLE = (1 << 5);
const DUK_DEFPROP_HAVE_VALUE = (1 << 6);
const DUK_DEFPROP_HAVE_GETTER = (1 << 7);
const DUK_DEFPROP_HAVE_SETTER = (1 << 8);
const DUK_DEFPROP_FORCE = (1 << 9);
}
}
bitflags! {
pub struct DukEnumFlags: u32 {
const DUK_ENUM_INCLUDE_NONENUMERABLE = (1 << 0);
const DUK_ENUM_INCLUDE_HIDDEN = (1 << 1);
const DUK_ENUM_INCLUDE_SYMBOLS = (1 << 2);
const DUK_ENUM_EXCLUDE_STRINGS = (1 << 3);
const DUK_ENUM_OWN_PROPERTIES_ONLY = (1 << 4);
const DUK_ENUM_ARRAY_INDICES_ONLY = (1 << 5);
const DUK_ENUM_SORT_ARRAY_INDICES = (1 << 6);
const DUK_ENUM_NO_PROXY_BEHAVIOR = (1 << 7);
}
}
bitflags! {
pub struct DukBufFlags: u32 {
const DUK_BUF_FLAG_DYNAMIC = (1 << 0);
const DUK_BUF_FLAG_EXTERNAL = (1 << 1);
const DUK_BUF_FLAG_NOZERO = (1 << 2);
}
}
bitflags! {
pub struct DukGcFlags: u32 {
const NONE = 0;
const DUK_GC_COMPACT = (1 << 0);
}
}
bitflags! {
pub struct DukThreadFlags: u32 {
const DUK_THREAD_NEW_GLOBAL_ENV = (1 << 0);
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(i32)]
#[allow(non_camel_case_types, dead_code)]
pub enum DukType {
DUK_TYPE_NONE = 0,
DUK_TYPE_UNDEFINED = 1,
DUK_TYPE_NULL = 2,
DUK_TYPE_BOOLEAN = 3,
DUK_TYPE_NUMBER = 4,
DUK_TYPE_STRING = 5,
DUK_TYPE_OBJECT = 6,
DUK_TYPE_BUFFER = 7,
DUK_TYPE_POINTER = 8,
DUK_TYPE_LIGHTFUNC = 9,
}
impl From<i32> for DukType {
fn from(e: i32) -> Self {
if e >= DukType::DUK_TYPE_NONE as i32 && e <= DukType::DUK_TYPE_LIGHTFUNC as i32 {
unsafe { std::mem::transmute(e) }
} else {
panic!("incorrect DukType value: {}", e); }
}
}
#[allow(non_camel_case_types)]
pub enum duk_context {}
#[allow(non_camel_case_types)]
pub type duk_fatal_function = extern "C" fn (udata: *mut c_void, msg: *const c_char);
#[allow(non_camel_case_types)]
pub type duk_alloc_function = extern "C" fn (udata: *mut c_void, size: usize) -> *mut c_void;
#[allow(non_camel_case_types)]
pub type duk_realloc_function = extern "C" fn (udata: *mut c_void, ptr: *mut c_void, size: usize) -> *mut c_void;
#[allow(non_camel_case_types)]
pub type duk_free_function = extern "C" fn (udata: *mut c_void, ptr: *mut c_void);
#[allow(non_camel_case_types)]
pub type duk_c_function = extern "C" fn(ctx: *mut duk_context) -> i32;
#[allow(non_camel_case_types)]
pub type duk_console_function = extern "C" fn(udata: *mut c_void, fun: u32, msg: *const c_char, msg_len: usize);
#[allow(dead_code)]
extern "C" {
pub fn duk_api_version() -> u32;
pub fn duk_api_git_describe() -> *const c_char;
pub fn duk_api_git_commit() -> *const c_char;
pub fn duk_api_git_branch() -> *const c_char;
pub fn duk_api_get_heap_udata(ctx: *mut duk_context) -> *mut c_void;
pub fn duk_api_console_init(ctx: *mut duk_context, console_func: Option<duk_console_function>);
pub fn duk_create_heap(alloc_func: Option<duk_alloc_function>,
realloc_func: Option<duk_realloc_function>,
free_func: Option<duk_free_function>,
heap_udata: *mut c_void,
fatal_handler: Option<duk_fatal_function>)
-> *mut duk_context;
pub fn duk_destroy_heap(ctx: *mut duk_context);
pub fn duk_eval_raw(ctx: *mut duk_context, code: *const c_char, len: usize, flags: u32) -> i32;
pub fn duk_compile_raw(ctx: *mut duk_context, code: *const c_char, len: usize, flags: u32) -> i32;
pub fn duk_call(ctx: *mut duk_context, nargs: i32);
pub fn duk_call_method(ctx: *mut duk_context, nargs: i32);
pub fn duk_call_prop(ctx: *mut duk_context, obj_index: i32, nargs: i32);
pub fn duk_pcall(ctx: *mut duk_context, nargs: i32) -> i32;
pub fn duk_pcall_method(ctx: *mut duk_context, nargs: i32) -> i32;
pub fn duk_pcall_prop(ctx: *mut duk_context, obj_index: i32, nargs: i32) -> i32;
pub fn duk_safe_to_lstring(ctx: *mut duk_context,
index: i32,
out_len: *mut usize)
-> *const c_char;
pub fn duk_get_top(ctx: *mut duk_context) -> i32;
pub fn duk_normalize_index(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_require_normalize_index(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_check_stack(ctx: *mut duk_context, extra: i32) -> bool;
pub fn duk_check_stack_top(ctx: *mut duk_context, top: i32) -> bool;
pub fn duk_dup(ctx: *mut duk_context, index: i32);
pub fn duk_remove(ctx: *mut duk_context, index: i32);
pub fn duk_pop(ctx: *mut duk_context);
pub fn duk_pop_1(ctx: *mut duk_context);
pub fn duk_pop_2(ctx: *mut duk_context);
pub fn duk_pop_n(ctx: *mut duk_context, n: i32);
pub fn duk_swap(ctx: *mut duk_context, idx1: i32, idx2: i32);
pub fn duk_xcopymove_raw(to_ctx: *mut duk_context, from_ctx: *mut duk_context, count: i32, is_copy: i32);
pub fn duk_push_null(ctx: *mut duk_context);
pub fn duk_push_undefined(ctx: *mut duk_context);
pub fn duk_push_boolean(ctx: *mut duk_context, val: i32);
pub fn duk_push_int(ctx: *mut duk_context, val: i32);
pub fn duk_push_uint(ctx: *mut duk_context, val: u32);
pub fn duk_push_number(ctx: *mut duk_context, val: f64);
pub fn duk_push_lstring(ctx: *mut duk_context, str: *const c_char, len: usize) -> *const c_char;
pub fn duk_push_array(ctx: *mut duk_context) -> i32;
pub fn duk_push_object(ctx: *mut duk_context) -> i32;
pub fn duk_push_pointer(ctx: *mut duk_context, p: *mut c_void);
pub fn duk_push_buffer_raw(ctx: *mut duk_context, len: usize, dynamic: u32) -> *mut c_void;
pub fn duk_push_c_function(ctx: *mut duk_context, func: Option<duk_c_function>, nargs: i32) -> i32;
pub fn duk_push_c_lightfunc(ctx: *mut duk_context, func: Option<duk_c_function>, nargs: i32, length: i32, magic: i32);
pub fn duk_push_current_function(ctx: *mut duk_context);
pub fn duk_push_this(ctx: *mut duk_context);
pub fn duk_push_thread_raw(ctx: *mut duk_context, flags: u32) -> i32;
pub fn duk_config_buffer(ctx: *mut duk_context, index: i32, ptr: *mut c_void, len: usize);
pub fn duk_get_type(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_get_length(ctx: *mut duk_context, index: i32) -> usize;
pub fn duk_get_context(ctx: *mut duk_context, index: i32) -> *mut duk_context;
pub fn duk_get_context_default(ctx: *mut duk_context, index: i32, def_value: *mut duk_context) -> *mut duk_context;
pub fn duk_samevalue(ctx: *mut duk_context, index1: i32, index2: i32) -> i32;
pub fn duk_is_array(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_is_object(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_is_number(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_is_string(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_is_function(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_is_thread(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_to_object(ctx: *mut duk_context, index: i32);
pub fn duk_to_number(ctx: *mut duk_context, index: i32) -> f64;
pub fn duk_to_string(ctx: *mut duk_context, index: i32) -> *const c_char;
pub fn duk_get_boolean(ctx: *mut duk_context, index: i32) -> i32;
pub fn duk_get_number(ctx: *mut duk_context, index: i32) -> f64;
pub fn duk_get_lstring(ctx: *mut duk_context, index: i32, len: Option<&mut usize>) -> *const c_char;
pub fn duk_get_buffer(ctx: *mut duk_context, index: i32, len: Option<&mut usize>) -> *mut c_void;
pub fn duk_get_pointer(ctx: *mut duk_context, index: i32) -> *mut c_void;
pub fn duk_get_prop(ctx: *mut duk_context, obj_index: i32) -> i32;
pub fn duk_put_prop(ctx: *mut duk_context, obj_index: i32) -> i32;
pub fn duk_def_prop(ctx: *mut duk_context, obj_index: i32, flags: u32);
pub fn duk_get_prop_lstring(ctx: *mut duk_context,
obj_index: i32,
key: *const c_char,
len: usize)
-> i32;
pub fn duk_put_prop_lstring(ctx: *mut duk_context,
obj_index: i32,
key: *const c_char,
len: usize)
-> i32;
pub fn duk_get_prop_index(ctx: *mut duk_context, obj_index: i32, index: u32) -> i32;
pub fn duk_put_prop_index(ctx: *mut duk_context, obj_index: i32, index: u32) -> i32;
pub fn duk_push_global_object(ctx: *mut duk_context);
pub fn duk_get_global_lstring(ctx: *mut duk_context, key: *const c_char, len: usize) -> i32;
pub fn duk_put_global_lstring(ctx: *mut duk_context, key: *const c_char, len: usize) -> i32;
pub fn duk_enum(ctx: *mut duk_context, obj_index: i32, flags: u32);
pub fn duk_next(ctx: *mut duk_context, enum_idx: i32, get_value: i32) -> i32;
pub fn duk_throw_raw(ctx: *mut duk_context);
pub fn duk_fatal(ctx: *mut duk_context, err_code: i32, err_msg: *const c_char);
pub fn duk_push_context_dump(ctx: *mut duk_context);
pub fn duk_set_global_object(ctx: *mut duk_context);
pub fn duk_gc(ctx: *mut duk_context, flags: u32);
}
#[inline(always)]
unsafe fn interop<'a>(udata: *mut c_void) -> &'a mut InteropRef {
&mut (*(udata as *mut Userdata)).interop
}
pub extern "C" fn alloc_func(udata: *mut c_void, size: usize) -> *mut c_void {
unsafe {
interop(udata).alloc(size) as *mut c_void
}
}
pub extern "C" fn realloc_func(udata: *mut c_void, ptr: *mut c_void, size: usize) -> *mut c_void {
unsafe {
interop(udata).realloc(ptr as *mut u8, size) as *mut c_void
}
}
pub extern "C" fn free_func(udata: *mut c_void, ptr: *mut c_void) {
unsafe {
interop(udata).free(ptr as *mut u8);
}
}
pub extern "C" fn console_func(udata: *mut c_void, func: u32, msg: *const c_char, len: usize) {
use std::str;
use std::slice;
unsafe {
let msg = str::from_utf8_unchecked(slice::from_raw_parts(msg as *const u8, len));
interop(udata).console(ConsoleFunc::from(func), msg);
}
}
pub extern "C" fn func_dispatch(ctx: *mut duk_context) -> i32 {
use std::str;
use std::slice;
unsafe {
duk_push_current_function(ctx);
duk_get_prop_lstring(ctx, -1, FUNC_NAME_PROP.as_ptr() as *const c_char, FUNC_NAME_PROP.len());
let mut len: usize = 0;
let ptr = duk_get_lstring(ctx, -1, Some(&mut len)) as *const u8;
let name = str::from_utf8_unchecked(slice::from_raw_parts(ptr, len));
duk_pop_2(ctx);
let udata = duk_api_get_heap_udata(ctx);
let mut duk_ctx = DukContext::from_raw(ctx);
let r = match interop(udata).call(&mut duk_ctx, name) {
Ok(r) => r,
Err(err) => {
let msg = format!("{err}");
duk_push_lstring(ctx, msg.as_ptr() as *const c_char, msg.len());
duk_throw_raw(ctx);
Return::Error
},
};
r as i32
}
}
pub extern "C" fn fatal_handler(udata: *mut c_void, msg: *const c_char) {
unsafe {
let msg = CStr::from_ptr(msg).to_string_lossy();
interop(udata).fatal(&msg);
}
}