diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a841377..9957e59e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ Breaking changes
* The traits `RegisterFn` and `RegisterResultFn` are removed. `Engine::register_fn` and `Engine::register_result_fn` are now implemented directly on `Engine`.
* `FnPtr::call_dynamic` now takes `&NativeCallContext` instead of consuming it.
+* All `Module::set_fn_XXX` methods are removed, in favor of `Module::set_native_fn`.
Version 0.19.14
diff --git a/src/engine_api.rs b/src/engine_api.rs
index 159e822c..eb6b97f5 100644
--- a/src/engine_api.rs
+++ b/src/engine_api.rs
@@ -51,8 +51,18 @@ impl Engine {
/// # Ok(())
/// # }
/// ```
- pub fn register_fn(&mut self, name: &str, func: impl RegisterNativeFunction) -> &mut Self {
- func.register_into(self, name);
+ pub fn register_fn(&mut self, name: &str, func: F) -> &mut Self
+ where
+ F: RegisterNativeFunction,
+ {
+ self.global_namespace.set_fn(
+ name,
+ FnNamespace::Global,
+ FnAccess::Public,
+ None,
+ &F::param_types(),
+ func.into_callable_function(),
+ );
self
}
/// Register a custom fallible function with the [`Engine`].
@@ -79,12 +89,18 @@ impl Engine {
/// engine.eval::("div(42, 0)")
/// .expect_err("expecting division by zero error!");
/// ```
- pub fn register_result_fn(
- &mut self,
- name: &str,
- func: impl RegisterNativeFunction,
- ) -> &mut Self {
- func.register_into(self, name);
+ pub fn register_result_fn(&mut self, name: &str, func: F) -> &mut Self
+ where
+ F: RegisterNativeFunction,
+ {
+ self.global_namespace.set_fn(
+ name,
+ FnNamespace::Global,
+ FnAccess::Public,
+ None,
+ &F::param_types(),
+ func.into_callable_function(),
+ );
self
}
/// Register a function of the [`Engine`].
@@ -803,8 +819,7 @@ impl Engine {
pub fn load_package(&mut self, module: impl Into>) -> &mut Self {
self.register_global_module(module.into())
}
- /// Register a shared [`Module`] as a static module namespace with the
- /// [`Engine`].
+ /// Register a shared [`Module`] as a static module namespace with the [`Engine`].
///
/// Functions marked [`FnNamespace::Global`] and type iterators are exposed to scripts without
/// namespace qualifications.
@@ -819,7 +834,7 @@ impl Engine {
///
/// // Create the module
/// let mut module = Module::new();
- /// module.set_fn_1("calc", |x: i64| Ok(x + 1));
+ /// module.set_native_fn("calc", |x: i64| Ok(x + 1));
///
/// let module: Shared = module.into();
///
diff --git a/src/fn_register.rs b/src/fn_register.rs
index 3d43cc3a..f53157a0 100644
--- a/src/fn_register.rs
+++ b/src/fn_register.rs
@@ -5,8 +5,8 @@
use crate::dynamic::{DynamicWriteLock, Variant};
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
use crate::r#unsafe::unsafe_try_cast;
-use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String};
-use crate::{Dynamic, Engine, FnAccess, FnNamespace, NativeCallContext, RhaiResult};
+use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String, vec};
+use crate::{Dynamic, EvalAltResult, NativeCallContext};
// These types are used to build a unique _marker_ tuple type for each combination
// of function parameter types in order to make each trait implementation unique.
@@ -53,10 +53,12 @@ pub fn by_value(data: &mut Dynamic) -> T {
}
}
-/// Trait to register custom functions with an [`Engine`].
+/// Trait to register custom Rust functions.
pub trait RegisterNativeFunction {
- /// Register the function with an [`Engine`].
- fn register_into(self, engine: &mut Engine, name: &str);
+ /// Get the types of this function's parameters.
+ fn param_types() -> Box<[TypeId]>;
+ /// Convert this function into a [`CallableFunction`].
+ fn into_callable_function(self) -> CallableFunction;
}
macro_rules! def_register {
@@ -77,21 +79,20 @@ macro_rules! def_register {
RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), ()> for FN {
#[inline(always)]
- fn register_into(self, engine: &mut Engine, name: &str) {
- engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None,
- &[$(TypeId::of::<$par>()),*],
- CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
- // The arguments are assumed to be of the correct number and types!
- let mut _drain = args.iter_mut();
- $($let $par = ($clone)(_drain.next().unwrap()); )*
+ fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)]
+ fn into_callable_function(self) -> CallableFunction {
+ CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
+ // The arguments are assumed to be of the correct number and types!
+ let mut _drain = args.iter_mut();
+ $($let $par = ($clone)(_drain.next().unwrap()); )*
- // Call the function with each argument value
- let r = self($($arg),*);
+ // Call the function with each argument value
+ let r = self($($arg),*);
- // Map the result
- Ok(r.into_dynamic())
- }) as Box)
- );
+ // Map the result
+ Ok(r.into_dynamic())
+ }) as Box)
}
}
@@ -101,61 +102,60 @@ macro_rules! def_register {
RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN {
#[inline(always)]
- fn register_into(self, engine: &mut Engine, name: &str) {
- engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None,
- &[$(TypeId::of::<$par>()),*],
- CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
- // The arguments are assumed to be of the correct number and types!
- let mut _drain = args.iter_mut();
- $($let $par = ($clone)(_drain.next().unwrap()); )*
+ fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)]
+ fn into_callable_function(self) -> CallableFunction {
+ CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
+ // The arguments are assumed to be of the correct number and types!
+ let mut _drain = args.iter_mut();
+ $($let $par = ($clone)(_drain.next().unwrap()); )*
- // Call the function with each argument value
- let r = self(ctx, $($arg),*);
+ // Call the function with each argument value
+ let r = self(ctx, $($arg),*);
- // Map the result
- Ok(r.into_dynamic())
- }) as Box)
- );
+ // Map the result
+ Ok(r.into_dynamic())
+ }) as Box)
}
}
impl<
- FN: Fn($($param),*) -> RhaiResult + SendSync + 'static,
+ FN: Fn($($param),*) -> Result> + SendSync + 'static,
$($par: Variant + Clone,)*
- > RegisterNativeFunction<($($mark,)*), RhaiResult> for FN {
+ RET: Variant + Clone
+ > RegisterNativeFunction<($($mark,)*), Result>> for FN {
#[inline(always)]
- fn register_into(self, engine: &mut Engine, name: &str) {
- engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None,
- &[$(TypeId::of::<$par>()),*],
- CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
- // The arguments are assumed to be of the correct number and types!
- let mut _drain = args.iter_mut();
- $($let $par = ($clone)(_drain.next().unwrap()); )*
+ fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)]
+ fn into_callable_function(self) -> CallableFunction {
+ CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| {
+ // The arguments are assumed to be of the correct number and types!
+ let mut _drain = args.iter_mut();
+ $($let $par = ($clone)(_drain.next().unwrap()); )*
- // Call the function with each argument value
- self($($arg),*)
- }) as Box)
- );
+ // Call the function with each argument value
+ self($($arg),*).map(Dynamic::from)
+ }) as Box)
}
}
impl<
- FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RhaiResult + SendSync + 'static,
+ FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> Result> + SendSync + 'static,
$($par: Variant + Clone,)*
- > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), RhaiResult> for FN {
+ RET: Variant + Clone
+ > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), Result>> for FN {
#[inline(always)]
- fn register_into(self, engine: &mut Engine, name: &str) {
- engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None,
- &[$(TypeId::of::<$par>()),*],
- CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
- // The arguments are assumed to be of the correct number and types!
- let mut _drain = args.iter_mut();
- $($let $par = ($clone)(_drain.next().unwrap()); )*
+ fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
+ #[inline(always)]
+ fn into_callable_function(self) -> CallableFunction {
+ CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
+ // The arguments are assumed to be of the correct number and types!
+ let mut _drain = args.iter_mut();
+ $($let $par = ($clone)(_drain.next().unwrap()); )*
- // Call the function with each argument value
- self(ctx, $($arg),*)
- }) as Box)
- );
+ // Call the function with each argument value
+ self(ctx, $($arg),*).map(Dynamic::from)
+ }) as Box)
}
}
diff --git a/src/module/mod.rs b/src/module/mod.rs
index 18c7f3f1..73e6aeea 100644
--- a/src/module/mod.rs
+++ b/src/module/mod.rs
@@ -3,7 +3,7 @@
use crate::ast::{FnAccess, Ident};
use crate::dynamic::Variant;
use crate::fn_native::{shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, SendSync};
-use crate::fn_register::by_value as cast_arg;
+use crate::fn_register::RegisterNativeFunction;
use crate::stdlib::{
any::TypeId,
boxed::Box,
@@ -607,7 +607,7 @@ impl Module {
/// Does the particular Rust function exist in the [`Module`]?
///
- /// The [`u64`] hash is returned by the `set_fn_XXX` calls.
+ /// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
///
/// # Example
///
@@ -615,7 +615,7 @@ impl Module {
/// use rhai::Module;
///
/// let mut module = Module::new();
- /// let hash = module.set_fn_0("calc", || Ok(42_i64));
+ /// let hash = module.set_native_fn("calc", || Ok(42_i64));
/// assert!(module.contains_fn(hash, true));
/// ```
#[inline(always)]
@@ -634,7 +634,7 @@ impl Module {
/// Update the metadata (parameter names/types and return type) of a registered function.
///
- /// The [`u64`] hash is returned by the `set_fn_XXX` calls.
+ /// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
///
/// ## Parameter Names and Types
///
@@ -654,7 +654,7 @@ impl Module {
/// Update the namespace of a registered function.
///
- /// The [`u64`] hash is returned by the `set_fn_XXX` calls.
+ /// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
#[inline(always)]
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
if let Some(f) = self.functions.get_mut(&hash_fn) {
@@ -822,13 +822,19 @@ impl Module {
)
}
- /// Set a Rust function taking no parameters into the [`Module`], returning a hash key.
+ /// Set a Rust function into the [`Module`], returning a hash key.
///
/// If there is a similar existing Rust function, it is replaced.
///
+ /// # Function Namespace
+ ///
+ /// The default function namespace is [`FnNamespace::Internal`].
+ /// Use [`update_fn_namespace`][Module::update_fn_namespace] to change it.
+ ///
/// # Function Metadata
///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
+ /// No metadata for the function is registered.
+ /// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
///
/// # Example
///
@@ -836,101 +842,22 @@ impl Module {
/// use rhai::Module;
///
/// let mut module = Module::new();
- /// let hash = module.set_fn_0("calc", || Ok(42_i64));
+ /// let hash = module.set_native_fn("calc", || Ok(42_i64));
/// assert!(module.contains_fn(hash, true));
/// ```
#[inline(always)]
- pub fn set_fn_0(
- &mut self,
- name: impl Into,
- func: impl Fn() -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, _: &mut FnCallArgs| func().map(Dynamic::from);
- let arg_types = [];
+ pub fn set_native_fn(&mut self, name: impl Into, func: F) -> u64
+ where
+ T: Variant + Clone,
+ F: RegisterNativeFunction>>,
+ {
self.set_fn(
name,
FnNamespace::Internal,
FnAccess::Public,
None,
- &arg_types,
- CallableFunction::from_pure(Box::new(f)),
- )
- }
-
- /// Set a Rust function taking one parameter into the [`Module`], returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::Module;
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_1(
- &mut self,
- name: impl Into,
- func: impl Fn(A) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- func(cast_arg::(&mut args[0])).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::()];
- self.set_fn(
- name,
- FnNamespace::Internal,
- FnAccess::Public,
- None,
- &arg_types,
- CallableFunction::from_pure(Box::new(f)),
- )
- }
-
- /// Set a Rust function taking one mutable parameter into the [`Module`], returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, FnNamespace};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_1_mut("calc", FnNamespace::Internal,
- /// |x: &mut i64| { *x += 1; Ok(*x) }
- /// );
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_1_mut(
- &mut self,
- name: impl Into,
- namespace: FnNamespace,
- func: impl Fn(&mut A) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- func(&mut args[0].write_lock::().unwrap()).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::()];
- self.set_fn(
- name,
- namespace,
- FnAccess::Public,
- None,
- &arg_types,
- CallableFunction::from_method(Box::new(f)),
+ &F::param_types(),
+ func.into_callable_function(),
)
}
@@ -954,104 +881,20 @@ impl Module {
/// ```
#[cfg(not(feature = "no_object"))]
#[inline(always)]
- pub fn set_getter_fn(
- &mut self,
- name: impl Into,
- func: impl Fn(&mut A) -> Result> + SendSync + 'static,
- ) -> u64 {
- self.set_fn_1_mut(
+ pub fn set_getter_fn(&mut self, name: impl Into, func: F) -> u64
+ where
+ A: Variant + Clone,
+ T: Variant + Clone,
+ F: RegisterNativeFunction>>,
+ F: Fn(&mut A) -> Result> + SendSync + 'static,
+ {
+ self.set_fn(
crate::engine::make_getter(&name.into()),
FnNamespace::Global,
- func,
- )
- }
-
- /// Set a Rust function taking two parameters into the [`Module`], returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, ImmutableString};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_2("calc", |x: i64, y: ImmutableString| {
- /// Ok(x + y.len() as i64)
- /// });
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_2(
- &mut self,
- name: impl Into,
- func: impl Fn(A, B) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let a = cast_arg::(&mut args[0]);
- let b = cast_arg::(&mut args[1]);
-
- func(a, b).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::(), TypeId::of::()];
- self.set_fn(
- name,
- FnNamespace::Internal,
FnAccess::Public,
None,
- &arg_types,
- CallableFunction::from_pure(Box::new(f)),
- )
- }
-
- /// Set a Rust function taking two parameters (the first one mutable) into the [`Module`],
- /// returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, FnNamespace, ImmutableString};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_2_mut("calc", FnNamespace::Internal,
- /// |x: &mut i64, y: ImmutableString| {
- /// *x += y.len() as i64;
- /// Ok(*x)
- /// }
- /// );
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_2_mut(
- &mut self,
- name: impl Into,
- namespace: FnNamespace,
- func: impl Fn(&mut A, B) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let b = cast_arg::(&mut args[1]);
- let a = &mut args[0].write_lock::().unwrap();
-
- func(a, b).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::(), TypeId::of::()];
- self.set_fn(
- name,
- namespace,
- FnAccess::Public,
- None,
- &arg_types,
- CallableFunction::from_method(Box::new(f)),
+ &F::param_types(),
+ func.into_callable_function(),
)
}
@@ -1079,15 +922,20 @@ impl Module {
/// ```
#[cfg(not(feature = "no_object"))]
#[inline(always)]
- pub fn set_setter_fn(
- &mut self,
- name: impl Into,
- func: impl Fn(&mut A, B) -> Result<(), Box> + SendSync + 'static,
- ) -> u64 {
- self.set_fn_2_mut(
+ pub fn set_setter_fn(&mut self, name: impl Into, func: F) -> u64
+ where
+ A: Variant + Clone,
+ B: Variant + Clone,
+ F: RegisterNativeFunction>>,
+ F: Fn(&mut A, B) -> Result<(), Box> + SendSync + 'static,
+ {
+ self.set_fn(
crate::engine::make_setter(&name.into()),
FnNamespace::Global,
- func,
+ FnAccess::Public,
+ None,
+ &F::param_types(),
+ func.into_callable_function(),
)
}
@@ -1119,10 +967,14 @@ impl Module {
/// ```
#[cfg(not(feature = "no_index"))]
#[inline(always)]
- pub fn set_indexer_get_fn(
- &mut self,
- func: impl Fn(&mut A, B) -> Result> + SendSync + 'static,
- ) -> u64 {
+ pub fn set_indexer_get_fn(&mut self, func: F) -> u64
+ where
+ A: Variant + Clone,
+ B: Variant + Clone,
+ T: Variant + Clone,
+ F: RegisterNativeFunction>>,
+ F: Fn(&mut A, B) -> Result> + SendSync + 'static,
+ {
if TypeId::of::() == TypeId::of::() {
panic!("Cannot register indexer for arrays.");
}
@@ -1137,107 +989,13 @@ impl Module {
panic!("Cannot register indexer for strings.");
}
- self.set_fn_2_mut(crate::engine::FN_IDX_GET, FnNamespace::Global, func)
- }
-
- /// Set a Rust function taking three parameters into the [`Module`], returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, ImmutableString};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_3("calc", |x: i64, y: ImmutableString, z: i64| {
- /// Ok(x + y.len() as i64 + z)
- /// });
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_3<
- A: Variant + Clone,
- B: Variant + Clone,
- C: Variant + Clone,
- T: Variant + Clone,
- >(
- &mut self,
- name: impl Into,
- func: impl Fn(A, B, C) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let a = cast_arg::(&mut args[0]);
- let b = cast_arg::(&mut args[1]);
- let c = cast_arg::(&mut args[2]);
-
- func(a, b, c).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()];
self.set_fn(
- name,
- FnNamespace::Internal,
+ crate::engine::FN_IDX_GET,
+ FnNamespace::Global,
FnAccess::Public,
None,
- &arg_types,
- CallableFunction::from_pure(Box::new(f)),
- )
- }
-
- /// Set a Rust function taking three parameters (the first one mutable) into the [`Module`],
- /// returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, FnNamespace, ImmutableString};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_3_mut("calc", FnNamespace::Internal,
- /// |x: &mut i64, y: ImmutableString, z: i64| {
- /// *x += y.len() as i64 + z;
- /// Ok(*x)
- /// }
- /// );
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_3_mut<
- A: Variant + Clone,
- B: Variant + Clone,
- C: Variant + Clone,
- T: Variant + Clone,
- >(
- &mut self,
- name: impl Into,
- namespace: FnNamespace,
- func: impl Fn(&mut A, B, C) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let b = cast_arg::(&mut args[2]);
- let c = cast_arg::(&mut args[3]);
- let a = &mut args[0].write_lock::().unwrap();
-
- func(a, b, c).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()];
- self.set_fn(
- name,
- namespace,
- FnAccess::Public,
- None,
- &arg_types,
- CallableFunction::from_method(Box::new(f)),
+ &F::param_types(),
+ func.into_callable_function(),
)
}
@@ -1270,10 +1028,14 @@ impl Module {
/// ```
#[cfg(not(feature = "no_index"))]
#[inline(always)]
- pub fn set_indexer_set_fn(
- &mut self,
- func: impl Fn(&mut A, B, C) -> Result<(), Box> + SendSync + 'static,
- ) -> u64 {
+ pub fn set_indexer_set_fn(&mut self, func: F) -> u64
+ where
+ A: Variant + Clone,
+ B: Variant + Clone,
+ C: Variant + Clone,
+ F: RegisterNativeFunction>>,
+ F: Fn(&mut A, B, C) -> Result<(), Box> + SendSync + 'static,
+ {
if TypeId::of::() == TypeId::of::() {
panic!("Cannot register indexer for arrays.");
}
@@ -1288,21 +1050,13 @@ impl Module {
panic!("Cannot register indexer for strings.");
}
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let b = cast_arg::(&mut args[1]);
- let c = cast_arg::(&mut args[2]);
- let a = &mut args[0].write_lock::().unwrap();
-
- func(a, b, c).map(Dynamic::from)
- };
- let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()];
self.set_fn(
crate::engine::FN_IDX_SET,
- FnNamespace::Internal,
+ FnNamespace::Global,
FnAccess::Public,
None,
- &arg_types,
- CallableFunction::from_method(Box::new(f)),
+ &F::param_types(),
+ func.into_callable_function(),
)
}
@@ -1352,124 +1106,9 @@ impl Module {
)
}
- /// Set a Rust function taking four parameters into the [`Module`], returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, ImmutableString};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_4("calc", |x: i64, y: ImmutableString, z: i64, _w: ()| {
- /// Ok(x + y.len() as i64 + z)
- /// });
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_4<
- A: Variant + Clone,
- B: Variant + Clone,
- C: Variant + Clone,
- D: Variant + Clone,
- T: Variant + Clone,
- >(
- &mut self,
- name: impl Into,
- func: impl Fn(A, B, C, D) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let a = cast_arg::(&mut args[0]);
- let b = cast_arg::(&mut args[1]);
- let c = cast_arg::(&mut args[2]);
- let d = cast_arg::(&mut args[3]);
-
- func(a, b, c, d).map(Dynamic::from)
- };
- let arg_types = [
- TypeId::of::(),
- TypeId::of::(),
- TypeId::of::(),
- TypeId::of::(),
- ];
- self.set_fn(
- name,
- FnNamespace::Internal,
- FnAccess::Public,
- None,
- &arg_types,
- CallableFunction::from_pure(Box::new(f)),
- )
- }
-
- /// Set a Rust function taking four parameters (the first one mutable) into the [`Module`],
- /// returning a hash key.
- ///
- /// If there is a similar existing Rust function, it is replaced.
- ///
- /// # Function Metadata
- ///
- /// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
- ///
- /// # Example
- ///
- /// ```
- /// use rhai::{Module, FnNamespace, ImmutableString};
- ///
- /// let mut module = Module::new();
- /// let hash = module.set_fn_4_mut("calc", FnNamespace::Internal,
- /// |x: &mut i64, y: ImmutableString, z: i64, _w: ()| {
- /// *x += y.len() as i64 + z;
- /// Ok(*x)
- /// }
- /// );
- /// assert!(module.contains_fn(hash, true));
- /// ```
- #[inline(always)]
- pub fn set_fn_4_mut<
- A: Variant + Clone,
- B: Variant + Clone,
- C: Variant + Clone,
- D: Variant + Clone,
- T: Variant + Clone,
- >(
- &mut self,
- name: impl Into,
- namespace: FnNamespace,
- func: impl Fn(&mut A, B, C, D) -> Result> + SendSync + 'static,
- ) -> u64 {
- let f = move |_: NativeCallContext, args: &mut FnCallArgs| {
- let b = cast_arg::(&mut args[1]);
- let c = cast_arg::(&mut args[2]);
- let d = cast_arg::(&mut args[3]);
- let a = &mut args[0].write_lock::().unwrap();
-
- func(a, b, c, d).map(Dynamic::from)
- };
- let arg_types = [
- TypeId::of::(),
- TypeId::of::(),
- TypeId::of::(),
- TypeId::of::(),
- ];
- self.set_fn(
- name,
- namespace,
- FnAccess::Public,
- None,
- &arg_types,
- CallableFunction::from_method(Box::new(f)),
- )
- }
-
/// Get a Rust function.
///
- /// The [`u64`] hash is returned by the `set_fn_XXX` calls.
+ /// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
#[inline(always)]
pub(crate) fn get_fn(&self, hash_fn: u64, public_only: bool) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).and_then(|f| match f.access {
diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs
index 2246a1d7..634435b8 100644
--- a/src/packages/iter_basic.rs
+++ b/src/packages/iter_basic.rs
@@ -141,7 +141,7 @@ macro_rules! reg_range {
($lib:ident | $x:expr => $( $y:ty ),*) => {
$(
$lib.set_iterator::>();
- let hash = $lib.set_fn_2($x, get_range::<$y>);
+ let hash = $lib.set_native_fn($x, get_range::<$y>);
$lib.update_fn_metadata(hash, &[
concat!("from: ", stringify!($y)),
concat!("to: ", stringify!($y)),
@@ -152,7 +152,7 @@ macro_rules! reg_range {
($lib:ident | step $x:expr => $( $y:ty ),*) => {
$(
$lib.set_iterator::>();
- let hash = $lib.set_fn_3($x, get_step_range::<$y>);
+ let hash = $lib.set_native_fn($x, get_step_range::<$y>);
$lib.update_fn_metadata(hash, &[
concat!("from: ", stringify!($y)),
concat!("to: ", stringify!($y)),
@@ -248,10 +248,10 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
lib.set_iterator::();
- let hash = lib.set_fn_2("range", |from, to| StepDecimalRange::new(from, to, Decimal::one()));
+ let hash = lib.set_native_fn("range", |from, to| StepDecimalRange::new(from, to, Decimal::one()));
lib.update_fn_metadata(hash, &["from: Decimal", "to: Decimal", "Iterator- "]);
- let hash = lib.set_fn_3("range", |from, to, step| StepDecimalRange::new(from, to, step));
+ let hash = lib.set_native_fn("range", |from, to, step| StepDecimalRange::new(from, to, step));
lib.update_fn_metadata(hash, &["from: Decimal", "to: Decimal", "step: Decimal", "Iterator
- "]);
}
});
diff --git a/src/packages/mod.rs b/src/packages/mod.rs
index 8e8fe21a..e54763da 100644
--- a/src/packages/mod.rs
+++ b/src/packages/mod.rs
@@ -53,8 +53,7 @@ pub trait Package {
/// Macro that makes it easy to define a _package_ (which is basically a shared [module][Module])
/// and register functions into it.
///
-/// Functions can be added to the package using the standard module methods such as
-/// [`set_fn_2`][Module::set_fn_2], [`set_fn_3_mut`][Module::set_fn_3_mut], [`set_fn_0`][Module::set_fn_0] etc.
+/// Functions can be added to the package using [`Module::set_native_fn`].
///
/// # Example
///
@@ -69,7 +68,7 @@ pub trait Package {
/// def_package!(rhai:MyPackage:"My super-duper package", lib,
/// {
/// // Load a binary function with all value parameters.
-/// lib.set_fn_2("my_add", add);
+/// lib.set_native_fn("my_add", add);
/// });
/// ```
#[macro_export]
diff --git a/tests/for.rs b/tests/for.rs
index 8827c123..65bca46f 100644
--- a/tests/for.rs
+++ b/tests/for.rs
@@ -171,7 +171,7 @@ fn test_for_module_iterator() -> Result<(), Box> {
// Set a type iterator deep inside a nested module chain
let mut sub_module = Module::new();
sub_module.set_iterable::();
- sub_module.set_fn_0("new_ts", || Ok(MyIterableType("hello".to_string())));
+ sub_module.set_native_fn("new_ts", || Ok(MyIterableType("hello".to_string())));
let mut module = Module::new();
module.set_sub_module("inner", sub_module);
diff --git a/tests/functions.rs b/tests/functions.rs
index 7f8fe26c..ff71e390 100644
--- a/tests/functions.rs
+++ b/tests/functions.rs
@@ -75,7 +75,7 @@ fn test_functions_namespaces() -> Result<(), Box> {
#[cfg(not(feature = "no_module"))]
{
let mut m = Module::new();
- let hash = m.set_fn_0("test", || Ok(999 as INT));
+ let hash = m.set_native_fn("test", || Ok(999 as INT));
m.update_fn_namespace(hash, FnNamespace::Global);
engine.register_static_module("hello", m.into());
diff --git a/tests/modules.rs b/tests/modules.rs
index 934b430d..fe4d6175 100644
--- a/tests/modules.rs
+++ b/tests/modules.rs
@@ -23,11 +23,12 @@ fn test_module_sub_module() -> Result<(), Box> {
let mut sub_module2 = Module::new();
sub_module2.set_var("answer", 41 as INT);
- let hash_inc = sub_module2.set_fn_1_mut("inc", FnNamespace::Internal, |x: &mut INT| Ok(*x + 1));
+ let hash_inc = sub_module2.set_native_fn("inc", |x: &mut INT| Ok(*x + 1));
sub_module2.build_index();
assert!(!sub_module2.contains_indexed_global_functions());
- sub_module2.set_fn_1_mut("super_inc", FnNamespace::Global, |x: &mut INT| Ok(*x + 1));
+ let super_hash = sub_module2.set_native_fn("super_inc", |x: &mut INT| Ok(*x + 1));
+ sub_module2.update_fn_namespace(super_hash, FnNamespace::Global);
sub_module2.build_index();
assert!(sub_module2.contains_indexed_global_functions());
@@ -91,16 +92,16 @@ fn test_module_resolver() -> Result<(), Box> {
let mut module = Module::new();
module.set_var("answer", 42 as INT);
- module.set_fn_4("sum", |x: INT, y: INT, z: INT, w: INT| Ok(x + y + z + w));
- module.set_fn_1_mut("double", FnNamespace::Global, |x: &mut INT| {
+ module.set_native_fn("sum", |x: INT, y: INT, z: INT, w: INT| Ok(x + y + z + w));
+ let double_hash = module.set_native_fn("double", |x: &mut INT| {
*x *= 2;
Ok(())
});
+ module.update_fn_namespace(double_hash, FnNamespace::Global);
#[cfg(not(feature = "no_float"))]
- module.set_fn_4_mut(
+ module.set_native_fn(
"sum_of_three_args",
- FnNamespace::Internal,
|target: &mut INT, a: INT, b: INT, c: rhai::FLOAT| {
*target = a + b + c as INT;
Ok(())
@@ -407,9 +408,9 @@ fn test_module_str() -> Result<(), Box> {
let mut engine = rhai::Engine::new();
let mut module = Module::new();
- module.set_fn_1("test", test_fn);
- module.set_fn_1("test2", test_fn2);
- module.set_fn_1("test3", test_fn3);
+ module.set_native_fn("test", test_fn);
+ module.set_native_fn("test2", test_fn2);
+ module.set_native_fn("test3", test_fn3);
let mut static_modules = rhai::module_resolvers::StaticModuleResolver::new();
static_modules.insert("test", module);