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);