use super::{
MetaCallClass, MetaCallException, MetaCallFunction, MetaCallFuture, MetaCallNull,
MetaCallObject, MetaCallPointer, MetaCallThrowable,
};
use crate::{
bindings::*,
cast, cstring,
helpers::{MetaCallClone, MetaCallDowncast},
match_metacall_value,
};
use std::{
collections::HashMap,
ffi::{c_char, c_int, c_void, CStr},
fmt::Debug,
slice,
};
pub trait MetaCallValue: MetaCallClone + MetaCallDowncast + Debug {
#[doc(hidden)]
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>>
where
Self: Sized,
{
let value = Self::from_metacall_raw_leak(v)?;
unsafe { metacall_value_destroy(v) };
Ok(value)
}
#[doc(hidden)]
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>>
where
Self: Sized;
#[doc(hidden)]
fn get_metacall_id() -> metacall_value_id
where
Self: Sized;
#[doc(hidden)]
fn into_metacall_raw(self) -> *mut c_void;
}
impl MetaCallValue for bool {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_BOOL
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_bool(v) != 0 };
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
unsafe { metacall_value_create_bool((self as c_int).try_into().unwrap()) }
}
}
impl MetaCallValue for char {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_CHAR
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_char(v) as u8 as char };
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
unsafe { metacall_value_create_char(self as c_char) }
}
}
impl MetaCallValue for i16 {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_SHORT
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_short(v) };
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
unsafe { metacall_value_create_short(self) }
}
}
impl MetaCallValue for i32 {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_INT
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_int(v) };
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
unsafe { metacall_value_create_int(self) }
}
}
impl MetaCallValue for i64 {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_LONG
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_long(v) };
Ok(value as i64)
}
fn into_metacall_raw(self) -> *mut c_void {
#[cfg(any(target_pointer_width = "32", windows))]
{
unsafe { metacall_value_create_long(self.try_into().unwrap()) }
}
#[cfg(not(any(target_pointer_width = "32", windows)))]
{
unsafe { metacall_value_create_long(self) }
}
}
}
impl MetaCallValue for f32 {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_FLOAT
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_float(v) };
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
unsafe { metacall_value_create_float(self) }
}
}
impl MetaCallValue for f64 {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_DOUBLE
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let value = unsafe { metacall_value_to_double(v) };
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
unsafe { metacall_value_create_double(self) }
}
}
impl MetaCallValue for String {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_STRING
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let c_str = unsafe { CStr::from_ptr(metacall_value_to_string(v)) };
let value = String::from(c_str.to_str().unwrap());
Ok(value)
}
fn into_metacall_raw(self) -> *mut c_void {
let raw = cstring!(self.as_str()).unwrap();
unsafe { metacall_value_create_string(raw.as_ptr(), self.len()) }
}
}
impl MetaCallValue for Vec<i8> {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_BUFFER
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(unsafe {
slice::from_raw_parts(
metacall_value_to_buffer(v) as *mut c_char,
metacall_value_size(v),
)
.to_vec()
})
}
fn into_metacall_raw(mut self) -> *mut c_void {
unsafe { metacall_value_create_buffer(self.as_mut_ptr() as *mut c_void, self.len()) }
}
}
impl<T: MetaCallValue + Clone> MetaCallValue for Vec<T> {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_ARRAY
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
let count = unsafe { metacall_value_count(v) };
let vec = unsafe { slice::from_raw_parts(metacall_value_to_array(v), count) }
.iter()
.map(|element| cast::raw_to_metacallobj_leak(*element))
.collect::<Result<Vec<T>, Box<dyn MetaCallValue>>>()?;
Ok(vec)
}
fn into_metacall_raw(self) -> *mut c_void {
let mut array = self
.into_iter()
.map(|element| element.into_metacall_raw().cast_const())
.collect::<Vec<*const c_void>>();
unsafe { metacall_value_create_array(array.as_mut_ptr(), array.len()) }
}
}
impl<T: MetaCallValue + Clone> MetaCallValue for HashMap<String, T> {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_MAP
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
unsafe {
let mut hashmap = HashMap::new();
for map_value in
slice::from_raw_parts(metacall_value_to_map(v), metacall_value_count(v)).iter()
{
let m_pair = slice::from_raw_parts(metacall_value_to_array(*map_value), 2);
let key = match_metacall_value!(cast::raw_to_metacallobj_untyped_leak(m_pair[0]), {
str: String => str,
num: i16 => num.to_string(),
num: i32 => num.to_string(),
num: i64 => num.to_string(),
num: f32 => num.to_string(),
num: f64 => num.to_string(),
_ => String::from("Invalid key!")
});
let val = match cast::raw_to_metacallobj_leak::<T>(m_pair[1]) {
Ok(parsed) => parsed,
Err(original) => {
return Err(original);
}
};
hashmap.insert(key, val);
}
Ok(hashmap)
}
}
fn into_metacall_raw(self) -> *mut c_void {
let mut hashmap: Vec<*const c_void> = self
.into_iter()
.map(|(key, value)| {
let key = key.into_metacall_raw();
let value = value.into_metacall_raw();
unsafe {
metacall_value_create_array(
vec![key as *const c_void, value as *const c_void].as_mut_ptr(),
2,
) as *const c_void
}
})
.collect();
unsafe { metacall_value_create_map(hashmap.as_mut_ptr(), hashmap.len()) }
}
}
impl MetaCallValue for MetaCallPointer {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_PTR
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Self::new_raw_leak(v)
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Self::new_raw(v)
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallFuture {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_FUTURE
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw_leak(v))
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw(v))
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallFunction {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_FUNCTION
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw_leak(v))
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw(v))
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallNull {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_NULL
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
unsafe { metacall_value_destroy(v) };
Ok(MetaCallNull())
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Self::from_metacall_raw_leak(v)
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallClass {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_CLASS
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw_leak(v))
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw(v))
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallObject {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_OBJECT
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw_leak(v))
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw(v))
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallException {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_EXCEPTION
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw_leak(v))
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw(v))
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for MetaCallThrowable {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_THROWABLE
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw_leak(v))
}
fn from_metacall_raw(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(Self::new_raw(v))
}
fn into_metacall_raw(self) -> *mut c_void {
self.into_raw()
}
}
impl MetaCallValue for Box<dyn MetaCallValue> {
fn get_metacall_id() -> metacall_value_id {
metacall_value_id::METACALL_INVALID
}
fn from_metacall_raw_leak(v: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
Ok(cast::raw_to_metacallobj_untyped_leak(v))
}
fn into_metacall_raw(self) -> *mut c_void {
match_metacall_value!(self, {
bool: bool => bool.into_metacall_raw(),
char: char => char.into_metacall_raw(),
num: i16 => num.into_metacall_raw(),
num: i32 => num.into_metacall_raw(),
num: i64 => num.into_metacall_raw(),
num: f32 => num.into_metacall_raw(),
num: f64 => num.into_metacall_raw(),
str: String => str.into_metacall_raw(),
buf: Vec<i8> => buf.into_metacall_raw(),
arr: Vec<Box<dyn MetaCallValue>> => arr.into_metacall_raw(),
map: HashMap<String, Box<dyn MetaCallValue>> => map.into_metacall_raw(),
ptr: MetaCallPointer => ptr.into_metacall_raw(),
fut: MetaCallFuture => fut.into_metacall_raw(),
fun: MetaCallFunction => fun.into_metacall_raw(),
null: MetaCallNull => null.into_metacall_raw(),
cls: MetaCallClass => cls.into_metacall_raw(),
obj: MetaCallObject => obj.into_metacall_raw(),
exc: MetaCallException => exc.into_metacall_raw(),
thr: MetaCallThrowable => thr.into_metacall_raw(),
_ => MetaCallNull().into_metacall_raw()
})
}
}