#![allow(non_snake_case)]
#![allow(unused_imports)]
#![allow(unused_mut)]
#![allow(unused_variables)]
use super::call::FnCallArgs;
use super::function::RhaiFunc;
use super::native::{SendSync, Shared};
use crate::types::dynamic::{DynamicWriteLock, Union, Variant};
use crate::{Dynamic, Identifier, NativeCallContext, RhaiResultOf};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
use std::{
any::{type_name, TypeId},
mem,
};
pub struct Mut<T>(T);
#[inline(always)]
pub fn by_ref<T: Variant + Clone>(data: &mut Dynamic) -> DynamicWriteLock<'_, T> {
data.write_lock::<T>().unwrap()
}
#[inline(always)]
#[must_use]
pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
if TypeId::of::<T>() == TypeId::of::<&str>() {
*data = data.take().flatten();
let ref_str = match data.0 {
Union::Str(ref s, ..) => s.as_str(),
_ => unreachable!(),
};
return unsafe { mem::transmute_copy::<_, T>(&ref_str) };
}
if TypeId::of::<T>() == TypeId::of::<String>() {
return reify! { data.take().into_string().unwrap() => !!! T };
}
data.take().cast::<T>()
}
pub trait RhaiNativeFunc<A: 'static, const N: usize, const X: bool, R: 'static, const F: bool> {
#[must_use]
fn into_rhai_function(self, is_pure: bool, is_volatile: bool) -> RhaiFunc;
#[must_use]
fn param_types() -> [TypeId; N];
#[inline(always)]
#[must_use]
fn num_params() -> usize {
N
}
#[inline(always)]
#[must_use]
fn has_context() -> bool {
X
}
#[cfg(feature = "metadata")]
#[must_use]
fn param_names() -> [&'static str; N];
#[cfg(feature = "metadata")]
#[inline(always)]
#[must_use]
fn return_type() -> TypeId {
if F {
TypeId::of::<RhaiResultOf<R>>()
} else {
TypeId::of::<R>()
}
}
#[cfg(feature = "metadata")]
#[inline(always)]
#[must_use]
fn return_type_name() -> &'static str {
type_name::<R>()
}
}
macro_rules! def_register {
() => {
def_register!(imp Pure : 0;);
};
(imp $abi:ident : $n:expr ; $($par:ident => $arg:expr => $mark:ty => $param:ty => $clone:expr),*) => {
impl<
FN: Fn($($param),*) -> RET + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone,
> RhaiNativeFunc<($($mark,)*), $n, false, RET, false> for FN {
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
#[inline(always)] fn into_rhai_function(self, is_pure: bool, is_volatile: bool) -> RhaiFunc {
RhaiFunc::$abi { func: Shared::new(move |_, args: &mut FnCallArgs| {
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
let r = self($($arg),*);
Ok(Dynamic::from(r))
}), has_context: false, is_pure, is_volatile }
}
}
impl<
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RET + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone,
> RhaiNativeFunc<($($mark,)*), $n, true, RET, false> for FN {
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
#[inline(always)] fn into_rhai_function(self, is_pure: bool, is_volatile: bool) -> RhaiFunc {
RhaiFunc::$abi { func: Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
let ctx = ctx.unwrap();
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
let r = self(ctx, $($arg),*);
Ok(Dynamic::from(r))
}), has_context: true, is_pure, is_volatile }
}
}
impl<
FN: Fn($($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone
> RhaiNativeFunc<($($mark,)*), $n, false, RET, true> for FN {
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::<RhaiResultOf<RET>>() }
#[inline(always)] fn into_rhai_function(self, is_pure: bool, is_volatile: bool) -> RhaiFunc {
RhaiFunc::$abi { func: Shared::new(move |_, args: &mut FnCallArgs| {
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
self($($arg),*).map(Dynamic::from)
}), has_context: false, is_pure, is_volatile }
}
}
impl<
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone
> RhaiNativeFunc<($($mark,)*), $n, true, RET, true> for FN {
#[inline(always)] fn param_types() -> [TypeId;$n] { [$(TypeId::of::<$par>()),*] }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> [&'static str;$n] { [$(type_name::<$param>()),*] }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { type_name::<RhaiResultOf<RET>>() }
#[inline(always)] fn into_rhai_function(self, is_pure: bool, is_volatile: bool) -> RhaiFunc {
RhaiFunc::$abi { func: Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
let ctx = ctx.unwrap();
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
self(ctx, $($arg),*).map(Dynamic::from)
}), has_context: true, is_pure, is_volatile }
}
}
};
($p0:ident:$n0:expr $(, $p:ident: $n:expr)*) => {
def_register!(imp Pure : $n0 ; $p0 => $p0 => $p0 => $p0 => by_value $(, $p => $p => $p => $p => by_value)*);
def_register!(imp Method : $n0 ; $p0 => &mut $p0 => Mut<$p0> => &mut $p0 => by_ref $(, $p => $p => $p => $p => by_value)*);
def_register!($($p:$n),*);
};
}
def_register!(A:20, B:19, C:18, D:17, E:16, F:15, G:14, H:13, J:12, K:11, L:10, M:9, N:8, P:7, Q:6, R:5, S:4, T:3, U:2, V:1);