use crate::{
bindings::{metacall_function, metacall_value_destroy, metacallfv_s, metacallhv_s},
cast, cstring_enum,
load::Handle,
types::{MetaCallError, MetaCallNull, MetaCallValue},
};
use std::ffi::c_void;
#[allow(unused_imports)]
use crate::match_metacall_value;
fn metacall_inner(
func: impl ToString,
args: impl IntoIterator<Item = impl MetaCallValue>,
) -> Result<*mut c_void, MetaCallError> {
let c_function = cstring_enum!(func, MetaCallError)?;
let c_func = unsafe { metacall_function(c_function.as_ptr()) };
if c_func.is_null() {
return Err(MetaCallError::FunctionNotFound);
}
let mut c_args = cast::metacallobj_to_raw_args(args);
let args_length = c_args.len();
let ret = unsafe { metacallfv_s(c_func, c_args.as_mut_ptr(), args_length) };
for c_arg in c_args {
unsafe { metacall_value_destroy(c_arg) };
}
Ok(ret)
}
fn metacall_inner_handle(
handle: &mut Handle,
func: impl ToString,
args: impl IntoIterator<Item = impl MetaCallValue>,
) -> Result<*mut c_void, MetaCallError> {
let c_function = cstring_enum!(func, MetaCallError)?;
let mut c_args = cast::metacallobj_to_raw_args(args);
let args_length = c_args.len();
let ret = unsafe {
metacallhv_s(
handle.as_mut_raw_ptr(),
c_function.as_ptr(),
c_args.as_mut_ptr(),
args_length,
)
};
for c_arg in c_args {
unsafe { metacall_value_destroy(c_arg) };
}
Ok(ret)
}
pub fn metacall_untyped(
func: impl ToString,
args: impl IntoIterator<Item = impl MetaCallValue>,
) -> Result<Box<dyn MetaCallValue>, MetaCallError> {
Ok(cast::raw_to_metacallobj_untyped(metacall_inner(
func, args,
)?))
}
pub fn metacall_untyped_no_arg(
func: impl ToString,
) -> Result<Box<dyn MetaCallValue>, MetaCallError> {
metacall_untyped(func, [] as [MetaCallNull; 0])
}
pub fn metacall<T: MetaCallValue>(
func: impl ToString,
args: impl IntoIterator<Item = impl MetaCallValue>,
) -> Result<T, MetaCallError> {
match cast::raw_to_metacallobj::<T>(metacall_inner(func, args)?) {
Ok(ret) => Ok(ret),
Err(original) => Err(MetaCallError::FailedCasting(original)),
}
}
pub fn metacall_handle<T: MetaCallValue>(
handle: &mut Handle,
func: impl ToString,
args: impl IntoIterator<Item = impl MetaCallValue>,
) -> Result<T, MetaCallError> {
match cast::raw_to_metacallobj::<T>(metacall_inner_handle(handle, func, args)?) {
Ok(ret) => Ok(ret),
Err(original) => Err(MetaCallError::FailedCasting(original)),
}
}
pub fn metacall_no_arg<T: MetaCallValue>(func: impl ToString) -> Result<T, MetaCallError> {
metacall::<T>(func, [] as [MetaCallNull; 0])
}
pub fn metacall_handle_no_arg<T: MetaCallValue>(
handle: &mut Handle,
func: impl ToString,
) -> Result<T, MetaCallError> {
metacall_handle::<T>(handle, func, [] as [MetaCallNull; 0])
}