#![allow(non_snake_case)]
#![allow(unused_imports)]
#![allow(unused_mut)]
#![allow(unused_variables)]
use super::call::FnCallArgs;
use super::callable_function::CallableFunction;
use super::native::{SendSync, Shared};
use crate::types::dynamic::{DynamicWriteLock, 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>().expect("checked")
}
#[inline(always)]
#[must_use]
pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
if TypeId::of::<T>() == TypeId::of::<&str>() {
data.flatten_in_place();
let ref_str = data.as_str_ref().expect("&str");
return unsafe { mem::transmute_copy::<_, T>(&ref_str) };
}
if TypeId::of::<T>() == TypeId::of::<String>() {
return reify! { mem::take(data).into_string().expect("`ImmutableString`") => T };
}
mem::take(data).cast::<T>()
}
pub trait RegisterNativeFunction<
A: 'static,
const N: usize,
const X: bool,
R: 'static,
const F: bool,
>
{
#[must_use]
fn into_callable_function(self, name: Identifier, no_const: bool) -> CallableFunction;
#[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! check_constant {
($abi:ident, $n:expr, $fn_name:ident, $no_const:ident, $args:ident) => {
#[cfg(any(not(feature = "no_object"), not(feature = "no_index")))]
if stringify!($abi) == "Method" && $no_const && $args[0].is_read_only() {
return Err(crate::ERR::ErrorNonPureMethodCallOnConstant(
$fn_name.to_string(),
crate::Position::NONE,
)
.into());
}
};
}
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,
> RegisterNativeFunction<($($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_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
CallableFunction::$abi { func: Shared::new(move |_, args: &mut FnCallArgs| {
check_constant!($abi, $n, fn_name, no_const, args);
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
let r = self($($arg),*);
Ok(Dynamic::from(r))
}), has_context: false }
}
}
impl<
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RET + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone,
> RegisterNativeFunction<($($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_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
CallableFunction::$abi { func: Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
let ctx = ctx.unwrap();
check_constant!($abi, $n, fn_name, no_const, args);
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 }
}
}
impl<
FN: Fn($($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone
> RegisterNativeFunction<($($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_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
CallableFunction::$abi { func: Shared::new(move |_, args: &mut FnCallArgs| {
check_constant!($abi, $n, fn_name, no_const, args);
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
self($($arg),*).map(Dynamic::from)
}), has_context: false }
}
}
impl<
FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RhaiResultOf<RET> + SendSync + 'static,
$($par: Variant + Clone,)*
RET: Variant + Clone
> RegisterNativeFunction<($($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_callable_function(self, fn_name: Identifier, no_const: bool) -> CallableFunction {
CallableFunction::$abi { func: Shared::new(move |ctx: Option<NativeCallContext>, args: &mut FnCallArgs| {
let ctx = ctx.unwrap();
check_constant!($abi, $n, fn_name, no_const, args);
let mut drain = args.iter_mut();
$(let mut $par = $clone(drain.next().unwrap()); )*
self(ctx, $($arg),*).map(Dynamic::from)
}), has_context: true }
}
}
};
($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);