diff --git a/CHANGELOG.md b/CHANGELOG.md index d9aecc83..a17f951c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,11 +10,15 @@ Bug fixes * API for registering property getters/setters and indexers to an `Engine` now works with functions that take a first parameter of `NativeCallContext`. * Missing API function `Module::set_getter_setter_fn` is added. +Deprecated API +-------------- + +* All versions of the `Engine::register_XXX_result` API that register a function returning `Result>` are now deprecated. The regular, non-`result` versions handle all functions correctly. + New features ------------ -Fallible type iterators ------------------------ +### Fallible type iterators * For very special needs, the ability to register fallible type iterators is added. diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 915b6741..22291c4f 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -303,7 +303,7 @@ pub fn register_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenS Ok((engine_expr, export_name, rust_mod_path)) => { let gen_mod_path = crate::register::generated_module_path(&rust_mod_path); proc_macro::TokenStream::from(quote! { - #engine_expr.register_result_fn(#export_name, #gen_mod_path::dynamic_result_fn) + #engine_expr.register_fn(#export_name, #gen_mod_path::dynamic_result_fn) }) } Err(e) => e.to_compile_error().into(), diff --git a/src/api/build_type.rs b/src/api/build_type.rs index 7b54fadf..20556eb7 100644 --- a/src/api/build_type.rs +++ b/src/api/build_type.rs @@ -1,11 +1,14 @@ //! Trait to build a custom type for use with [`Engine`]. #![allow(deprecated)] -use crate::{types::dynamic::Variant, Engine, Identifier, RegisterNativeFunction, RhaiResultOf}; +use crate::{types::dynamic::Variant, Engine, Identifier, RegisterNativeFunction}; use std::marker::PhantomData; #[cfg(feature = "no_std")] use std::prelude::v1::*; +#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] +use crate::func::register::Mut; + /// Trait to build the API of a custom type for use with an [`Engine`] /// (i.e. register the type and its getters, setters, methods, etc.). /// @@ -133,17 +136,6 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> { self.engine.register_fn(name, method); self } - - /// Register a custom fallible function. - #[inline(always)] - pub fn with_result_fn(&mut self, name: N, method: F) -> &mut Self - where - N: AsRef + Into, - F: RegisterNativeFunction>, - { - self.engine.register_result_fn(name, method); - self - } } impl<'a, T> TypeBuilder<'a, T> @@ -168,67 +160,39 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> { /// /// Not available under `no_object`. #[inline(always)] - pub fn with_get( + pub fn with_get( &mut self, name: impl AsRef, - get_fn: impl Fn(&mut T) -> V + crate::func::SendSync + 'static, + get_fn: impl RegisterNativeFunction<(Mut,), V, S> + crate::func::SendSync + 'static, ) -> &mut Self { self.engine.register_get(name, get_fn); self } - /// Register a fallible getter function. - /// - /// The function signature must start with `&mut self` and not `&self`. - /// - /// Not available under `no_object`. - #[inline(always)] - pub fn with_get_result( - &mut self, - name: impl AsRef, - get_fn: impl Fn(&mut T) -> RhaiResultOf + crate::func::SendSync + 'static, - ) -> &mut Self { - self.engine.register_get_result(name, get_fn); - self - } - /// Register a setter function. /// /// Not available under `no_object`. #[inline(always)] - pub fn with_set( + pub fn with_set( &mut self, name: impl AsRef, - set_fn: impl Fn(&mut T, V) + crate::func::SendSync + 'static, + set_fn: impl RegisterNativeFunction<(Mut, V), (), S> + crate::func::SendSync + 'static, ) -> &mut Self { self.engine.register_set(name, set_fn); self } - /// Register a fallible setter function. - /// - /// Not available under `no_object`. - #[inline(always)] - pub fn with_set_result( - &mut self, - name: impl AsRef, - set_fn: impl Fn(&mut T, V) -> RhaiResultOf<()> + crate::func::SendSync + 'static, - ) -> &mut Self { - self.engine.register_set_result(name, set_fn); - self - } - /// Short-hand for registering both getter and setter functions. /// /// All function signatures must start with `&mut self` and not `&self`. /// /// Not available under `no_object`. #[inline(always)] - pub fn with_get_set( + pub fn with_get_set( &mut self, name: impl AsRef, - get_fn: impl Fn(&mut T) -> V + crate::func::SendSync + 'static, - set_fn: impl Fn(&mut T, V) + crate::func::SendSync + 'static, + get_fn: impl RegisterNativeFunction<(Mut,), V, S1> + crate::func::SendSync + 'static, + set_fn: impl RegisterNativeFunction<(Mut, V), (), S2> + crate::func::SendSync + 'static, ) -> &mut Self { self.engine.register_get_set(name, get_fn, set_fn); self @@ -243,60 +207,34 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> { /// /// Not available under both `no_index` and `no_object`. #[inline(always)] - pub fn with_indexer_get( + pub fn with_indexer_get( &mut self, - get_fn: impl Fn(&mut T, X) -> V + crate::func::SendSync + 'static, + get_fn: impl RegisterNativeFunction<(Mut, X), V, S> + crate::func::SendSync + 'static, ) -> &mut Self { self.engine.register_indexer_get(get_fn); self } - /// Register an fallible index getter. - /// - /// The function signature must start with `&mut self` and not `&self`. - /// - /// Not available under both `no_index` and `no_object`. - #[inline(always)] - pub fn with_indexer_get_result( - &mut self, - get_fn: impl Fn(&mut T, X) -> RhaiResultOf + crate::func::SendSync + 'static, - ) -> &mut Self { - self.engine.register_indexer_get_result(get_fn); - self - } - /// Register an index setter. /// /// Not available under both `no_index` and `no_object`. #[inline(always)] - pub fn with_indexer_set( + pub fn with_indexer_set( &mut self, - set_fn: impl Fn(&mut T, X, V) + crate::func::SendSync + 'static, + set_fn: impl RegisterNativeFunction<(Mut, X, V), (), S> + crate::func::SendSync + 'static, ) -> &mut Self { self.engine.register_indexer_set(set_fn); self } - /// Register an fallible index setter. - /// - /// Not available under both `no_index` and `no_object`. - #[inline(always)] - pub fn with_indexer_set_result( - &mut self, - set_fn: impl Fn(&mut T, X, V) -> RhaiResultOf<()> + crate::func::SendSync + 'static, - ) -> &mut Self { - self.engine.register_indexer_set_result(set_fn); - self - } - /// Short-hand for registering both index getter and setter functions. /// /// Not available under both `no_index` and `no_object`. #[inline(always)] - pub fn with_indexer_get_set( + pub fn with_indexer_get_set( &mut self, - get_fn: impl Fn(&mut T, X) -> V + crate::func::SendSync + 'static, - set_fn: impl Fn(&mut T, X, V) + crate::func::SendSync + 'static, + get_fn: impl RegisterNativeFunction<(Mut, X), V, S1> + crate::func::SendSync + 'static, + set_fn: impl RegisterNativeFunction<(Mut, X, V), (), S2> + crate::func::SendSync + 'static, ) -> &mut Self { self.engine.register_indexer_get_set(get_fn, set_fn); self diff --git a/src/api/deprecated.rs b/src/api/deprecated.rs index 208c3f2a..b1a06279 100644 --- a/src/api/deprecated.rs +++ b/src/api/deprecated.rs @@ -1,12 +1,17 @@ //! Module containing all deprecated API that will be removed in the next major version. +use crate::func::RegisterNativeFunction; +use crate::types::dynamic::Variant; use crate::{ - Dynamic, Engine, EvalAltResult, FnPtr, ImmutableString, NativeCallContext, Position, - RhaiResult, RhaiResultOf, Scope, AST, + Dynamic, Engine, EvalAltResult, FnPtr, Identifier, ImmutableString, NativeCallContext, + Position, RhaiResult, RhaiResultOf, Scope, AST, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; +#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] +use crate::func::register::Mut; + #[cfg(not(feature = "no_std"))] #[cfg(not(target_family = "wasm"))] use std::path::PathBuf; @@ -115,58 +120,6 @@ impl Engine { /// This method is deprecated. Use [`run_ast_with_scope`][Engine::run_ast_with_scope] instead. /// /// This method will be removed in the next major version. - /// - /// # WARNING - Low Level API - /// - /// This function is very low level. - /// - /// # Arguments - /// - /// All the arguments are _consumed_, meaning that they're replaced by `()`. - /// This is to avoid unnecessarily cloning the arguments. - /// - /// Do not use the arguments after this call. If they are needed afterwards, - /// clone them _before_ calling this function. - /// - /// # Example - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// # #[cfg(not(feature = "no_function"))] - /// # { - /// use rhai::{Engine, Scope, Dynamic}; - /// - /// let engine = Engine::new(); - /// - /// let ast = engine.compile(" - /// fn add(x, y) { len(x) + y + foo } - /// fn add1(x) { len(x) + 1 + foo } - /// fn bar() { foo/2 } - /// fn action(x) { this += x; } // function using 'this' pointer - /// ")?; - /// - /// let mut scope = Scope::new(); - /// scope.push("foo", 42_i64); - /// - /// // Call the script-defined function - /// let result = engine.call_fn_dynamic(&mut scope, &ast, true, "add", None, [ "abc".into(), 123_i64.into() ])?; - /// // ^^^^ no 'this' pointer - /// assert_eq!(result.cast::(), 168); - /// - /// let result = engine.call_fn_dynamic(&mut scope, &ast, true, "add1", None, [ "abc".into() ])?; - /// assert_eq!(result.cast::(), 46); - /// - /// let result = engine.call_fn_dynamic(&mut scope, &ast, true, "bar", None, [])?; - /// assert_eq!(result.cast::(), 21); - /// - /// let mut value: Dynamic = 1_i64.into(); - /// let result = engine.call_fn_dynamic(&mut scope, &ast, true, "action", Some(&mut value), [ 41_i64.into() ])?; - /// // ^^^^^^^^^^^^^^^^ binding the 'this' pointer - /// assert_eq!(value.as_int().expect("value should be INT"), 42); - /// # } - /// # Ok(()) - /// # } - /// ``` #[deprecated(since = "1.1.0", note = "use `call_fn_raw` instead")] #[cfg(not(feature = "no_function"))] #[inline(always)] @@ -181,6 +134,130 @@ impl Engine { ) -> RhaiResult { self.call_fn_raw(scope, ast, eval_ast, true, name, this_ptr, arg_values) } + /// Register a custom fallible function with the [`Engine`]. + /// + /// # Deprecated + /// + /// This method is deprecated. Use [`register_fn`][Engine::register_fn] instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `register_fn` instead")] + #[inline(always)] + pub fn register_result_fn(&mut self, name: N, func: F) -> &mut Self + where + N: AsRef + Into, + F: RegisterNativeFunction>, + { + self.register_fn(name, func) + } + /// Register a getter function for a member of a registered type with the [`Engine`]. + /// + /// The function signature must start with `&mut self` and not `&self`. + /// + /// Not available under `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use [`register_get`][Engine::register_get] instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `register_get` instead")] + #[cfg(not(feature = "no_object"))] + #[inline(always)] + pub fn register_get_result( + &mut self, + name: impl AsRef, + get_fn: impl RegisterNativeFunction<(Mut,), V, RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.register_get(name, get_fn) + } + /// Register a setter function for a member of a registered type with the [`Engine`]. + /// + /// Not available under `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use [`register_set`][Engine::register_set] instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `register_set` instead")] + #[cfg(not(feature = "no_object"))] + #[inline(always)] + pub fn register_set_result( + &mut self, + name: impl AsRef, + set_fn: impl RegisterNativeFunction<(Mut, V), (), RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.register_set(name, set_fn) + } + /// Register an index getter for a custom type with the [`Engine`]. + /// + /// The function signature must start with `&mut self` and not `&self`. + /// + /// Not available under both `no_index` and `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use [`register_indexer_get`][Engine::register_indexer_get] instead. + /// + /// This method will be removed in the next major version. + /// + /// # Panics + /// + /// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`], + /// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT]. + /// Indexers for arrays, object maps, strings and integers cannot be registered. + #[deprecated(since = "1.9.1", note = "use `register_indexer_get` instead")] + #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] + #[inline(always)] + pub fn register_indexer_get_result< + T: Variant + Clone, + X: Variant + Clone, + V: Variant + Clone, + S, + >( + &mut self, + get_fn: impl RegisterNativeFunction<(Mut, X), V, RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.register_indexer_get(get_fn) + } + /// Register an index setter for a custom type with the [`Engine`]. + /// + /// Not available under both `no_index` and `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use [`register_indexer_set`][Engine::register_indexer_set] instead. + /// + /// This method will be removed in the next major version. + /// + /// # Panics + /// + /// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`], + /// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT]. + /// Indexers for arrays, object maps, strings and integers cannot be registered. + #[deprecated(since = "1.9.1", note = "use `register_indexer_set` instead")] + #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] + #[inline(always)] + pub fn register_indexer_set_result< + T: Variant + Clone, + X: Variant + Clone, + V: Variant + Clone, + S, + >( + &mut self, + set_fn: impl RegisterNativeFunction<(Mut, X, V), (), RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.register_indexer_set(set_fn) + } } impl Dynamic { @@ -217,21 +294,6 @@ impl Dynamic { impl NativeCallContext<'_> { /// Call a function inside the call context. /// - /// # WARNING - Low Level API - /// - /// This function is very low level. - /// - /// # Arguments - /// - /// All arguments may be _consumed_, meaning that they may be replaced by `()`. This is to avoid - /// unnecessarily cloning the arguments. - /// - /// Do not use the arguments after this call. If they are needed afterwards, clone them _before_ - /// calling this function. - /// - /// If `is_method` is [`true`], the first argument is assumed to be passed by reference and is - /// not consumed. - /// /// # Deprecated /// /// This method is deprecated. Use [`call_fn_raw`][NativeCallContext::call_fn_raw] instead. @@ -285,18 +347,6 @@ impl FnPtr { /// [`call_raw`][FnPtr::call_raw] instead. /// /// This method will be removed in the next major version. - /// - /// # WARNING - Low Level API - /// - /// This function is very low level. - /// - /// # Arguments - /// - /// All the arguments are _consumed_, meaning that they're replaced by `()`. - /// This is to avoid unnecessarily cloning the arguments. - /// - /// Do not use the arguments after this call. If they are needed afterwards, - /// clone them _before_ calling this function. #[deprecated( since = "1.3.0", note = "use `call_within_context` or `call_raw` instead" @@ -352,3 +402,113 @@ impl Position { } } } + +#[allow(deprecated)] +impl<'a, T: Variant + Clone> crate::TypeBuilder<'a, T> { + /// Register a custom fallible function. + /// + /// # Deprecated + /// + /// This method is deprecated. Use `with_fn` instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `with_fn` instead")] + #[inline(always)] + pub fn with_result_fn(&mut self, name: N, method: F) -> &mut Self + where + N: AsRef + Into, + F: RegisterNativeFunction>, + { + self.with_fn(name, method) + } + + /// Register a fallible getter function. + /// + /// The function signature must start with `&mut self` and not `&self`. + /// + /// Not available under `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use `with_get` instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `with_get` instead")] + #[cfg(not(feature = "no_object"))] + #[inline(always)] + pub fn with_get_result( + &mut self, + name: impl AsRef, + get_fn: impl RegisterNativeFunction<(Mut,), V, RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.with_get(name, get_fn) + } + + /// Register a fallible setter function. + /// + /// Not available under `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use `with_set` instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `with_set` instead")] + #[cfg(not(feature = "no_object"))] + #[inline(always)] + pub fn with_set_result( + &mut self, + name: impl AsRef, + set_fn: impl RegisterNativeFunction<(Mut, V), (), RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.with_set(name, set_fn) + } + + /// Register an fallible index getter. + /// + /// The function signature must start with `&mut self` and not `&self`. + /// + /// Not available under both `no_index` and `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use `with_indexer_get` instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `with_indexer_get` instead")] + #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] + #[inline(always)] + pub fn with_indexer_get_result( + &mut self, + get_fn: impl RegisterNativeFunction<(Mut, X), V, RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.with_indexer_get(get_fn) + } + + /// Register an fallible index setter. + /// + /// Not available under both `no_index` and `no_object`. + /// + /// # Deprecated + /// + /// This method is deprecated. Use `with_indexer_set` instead. + /// + /// This method will be removed in the next major version. + #[deprecated(since = "1.9.1", note = "use `with_indexer_set` instead")] + #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] + #[inline(always)] + pub fn with_indexer_set_result( + &mut self, + set_fn: impl RegisterNativeFunction<(Mut, X, V), (), RhaiResultOf> + + crate::func::SendSync + + 'static, + ) -> &mut Self { + self.with_indexer_set(set_fn) + } +} diff --git a/src/api/register.rs b/src/api/register.rs index 5625773d..01b4f048 100644 --- a/src/api/register.rs +++ b/src/api/register.rs @@ -1,6 +1,5 @@ //! Module that defines the public function/module registration API of [`Engine`]. -use crate::func::register::Mut; use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync}; use crate::types::dynamic::Variant; use crate::{ @@ -10,6 +9,9 @@ use std::any::{type_name, TypeId}; #[cfg(feature = "no_std")] use std::prelude::v1::*; +#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] +use crate::func::register::Mut; + impl Engine { /// Get the global namespace module (which is the fist module in `global_modules`). #[inline(always)] @@ -88,64 +90,6 @@ impl Engine { ); self } - /// Register a custom fallible function with the [`Engine`]. - /// - /// # Example - /// - /// ``` - /// use rhai::{Engine, EvalAltResult}; - /// - /// // Normal function - /// fn div(x: i64, y: i64) -> Result> { - /// if y == 0 { - /// // '.into()' automatically converts to 'Box' - /// Err("division by zero!".into()) - /// } else { - /// Ok(x / y) - /// } - /// } - /// - /// let mut engine = Engine::new(); - /// - /// engine.register_result_fn("div", div); - /// - /// engine.eval::("div(42, 0)") - /// .expect_err("expecting division by zero error!"); - /// ``` - #[inline] - pub fn register_result_fn(&mut self, name: N, func: F) -> &mut Self - where - N: AsRef + Into, - F: RegisterNativeFunction>, - { - let param_types = F::param_types(); - - #[cfg(feature = "metadata")] - let param_type_names: crate::StaticVec<_> = F::param_names() - .iter() - .map(|ty| format!("_: {}", self.format_type_name(ty))) - .chain(Some(self.format_type_name(F::return_type_name()).into())) - .collect(); - - #[cfg(feature = "metadata")] - let param_type_names: crate::StaticVec<_> = - param_type_names.iter().map(String::as_str).collect(); - #[cfg(feature = "metadata")] - let param_type_names = Some(param_type_names.as_ref()); - - #[cfg(not(feature = "metadata"))] - let param_type_names: Option<&[&str]> = None; - - self.global_namespace_mut().set_fn( - name, - FnNamespace::Global, - FnAccess::Public, - param_type_names, - param_types, - func.into_callable_function(), - ); - self - } /// Register a function of the [`Engine`]. /// /// # WARNING - Low Level API @@ -363,55 +307,6 @@ impl Engine { ) -> &mut Self { self.register_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn) } - /// Register a getter function for a member of a registered type with the [`Engine`]. - /// - /// The function signature must start with `&mut self` and not `&self`. - /// - /// Not available under `no_object`. - /// - /// # Example - /// - /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult}; - /// - /// #[derive(Clone)] - /// struct TestStruct { - /// field: i64 - /// } - /// - /// impl TestStruct { - /// fn new() -> Self { - /// Self { field: 1 } - /// } - /// // Even a getter must start with `&mut self` and not `&self`. - /// fn get_field(&mut self) -> Result> { - /// Ok(self.field) - /// } - /// } - /// - /// # fn main() -> Result<(), Box> { - /// let mut engine = Engine::new(); - /// - /// // Register API for the custom type. - /// engine - /// .register_type::() - /// .register_fn("new_ts", TestStruct::new) - /// // Register a getter on a property (notice it doesn't have to be the same name). - /// .register_get_result("xyz", TestStruct::get_field); - /// - /// assert_eq!(engine.eval::("let a = new_ts(); a.xyz")?, 1); - /// # Ok(()) - /// # } - /// ``` - #[cfg(not(feature = "no_object"))] - #[inline(always)] - pub fn register_get_result( - &mut self, - name: impl AsRef, - get_fn: impl RegisterNativeFunction<(Mut,), V, RhaiResultOf> + SendSync + 'static, - ) -> &mut Self { - self.register_result_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn) - } /// Register a setter function for a member of a registered type with the [`Engine`]. /// /// Not available under `no_object`. @@ -462,57 +357,6 @@ impl Engine { ) -> &mut Self { self.register_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn) } - /// Register a setter function for a member of a registered type with the [`Engine`]. - /// - /// Not available under `no_object`. - /// - /// # Example - /// - /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult}; - /// - /// #[derive(Debug, Clone, Eq, PartialEq)] - /// struct TestStruct { - /// field: i64 - /// } - /// - /// impl TestStruct { - /// fn new() -> Self { - /// Self { field: 1 } - /// } - /// fn set_field(&mut self, new_val: i64) -> Result<(), Box> { - /// self.field = new_val; - /// Ok(()) - /// } - /// } - /// - /// # fn main() -> Result<(), Box> { - /// let mut engine = Engine::new(); - /// - /// // Register API for the custom type. - /// engine - /// .register_type::() - /// .register_fn("new_ts", TestStruct::new) - /// // Register a setter on a property (notice it doesn't have to be the same name) - /// .register_set_result("xyz", TestStruct::set_field); - /// - /// // Notice that, with a getter, there is no way to get the property value - /// assert_eq!( - /// engine.eval::("let a = new_ts(); a.xyz = 42; a")?, - /// TestStruct { field: 42 } - /// ); - /// # Ok(()) - /// # } - /// ``` - #[cfg(not(feature = "no_object"))] - #[inline(always)] - pub fn register_set_result( - &mut self, - name: impl AsRef, - set_fn: impl RegisterNativeFunction<(Mut, V), (), RhaiResultOf> + SendSync + 'static, - ) -> &mut Self { - self.register_result_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn) - } /// Short-hand for registering both getter and setter functions /// of a registered type with the [`Engine`]. /// @@ -643,86 +487,6 @@ impl Engine { self.register_fn(crate::engine::FN_IDX_GET, get_fn) } - /// Register an index getter for a custom type with the [`Engine`]. - /// - /// The function signature must start with `&mut self` and not `&self`. - /// - /// Not available under both `no_index` and `no_object`. - /// - /// # Panics - /// - /// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`], - /// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT]. - /// Indexers for arrays, object maps, strings and integers cannot be registered. - /// - /// # Example - /// - /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult}; - /// - /// #[derive(Clone)] - /// struct TestStruct { - /// fields: Vec - /// } - /// - /// impl TestStruct { - /// fn new() -> Self { - /// Self { fields: vec![1, 2, 3, 4, 5] } - /// } - /// // Even a getter must start with `&mut self` and not `&self`. - /// fn get_field(&mut self, index: i64) -> Result> { - /// Ok(self.fields[index as usize]) - /// } - /// } - /// - /// # fn main() -> Result<(), Box> { - /// let mut engine = Engine::new(); - /// - /// // Register API for the custom type. - /// # #[cfg(not(feature = "no_object"))] - /// engine.register_type::(); - /// - /// engine - /// .register_fn("new_ts", TestStruct::new) - /// // Register an indexer. - /// .register_indexer_get_result(TestStruct::get_field); - /// - /// # #[cfg(not(feature = "no_index"))] - /// assert_eq!(engine.eval::("let a = new_ts(); a[2]")?, 3); - /// # Ok(()) - /// # } - /// ``` - #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] - #[inline] - pub fn register_indexer_get_result< - T: Variant + Clone, - X: Variant + Clone, - V: Variant + Clone, - S, - >( - &mut self, - get_fn: impl RegisterNativeFunction<(Mut, X), V, RhaiResultOf> + SendSync + 'static, - ) -> &mut Self { - #[cfg(not(feature = "no_index"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for arrays."); - } - #[cfg(not(feature = "no_object"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for object maps."); - } - if TypeId::of::() == TypeId::of::() - || TypeId::of::() == TypeId::of::<&str>() - || TypeId::of::() == TypeId::of::() - { - panic!("Cannot register indexer for strings."); - } - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for integers."); - } - - self.register_result_fn(crate::engine::FN_IDX_GET, get_fn) - } /// Register an index setter for a custom type with the [`Engine`]. /// /// Not available under both `no_index` and `no_object`. @@ -798,87 +562,6 @@ impl Engine { self.register_fn(crate::engine::FN_IDX_SET, set_fn) } - /// Register an index setter for a custom type with the [`Engine`]. - /// - /// Not available under both `no_index` and `no_object`. - /// - /// # Panics - /// - /// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`], - /// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT]. - /// Indexers for arrays, object maps, strings and integers cannot be registered. - /// - /// # Example - /// - /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult}; - /// - /// #[derive(Clone)] - /// struct TestStruct { - /// fields: Vec - /// } - /// - /// impl TestStruct { - /// fn new() -> Self { - /// Self { fields: vec![1, 2, 3, 4, 5] } - /// } - /// fn set_field(&mut self, index: i64, value: i64) -> Result<(), Box> { - /// self.fields[index as usize] = value; - /// Ok(()) - /// } - /// } - /// - /// # fn main() -> Result<(), Box> { - /// let mut engine = Engine::new(); - /// - /// // Register API for the custom type. - /// # #[cfg(not(feature = "no_object"))] - /// engine.register_type::(); - /// - /// engine - /// .register_fn("new_ts", TestStruct::new) - /// // Register an indexer. - /// .register_indexer_set_result(TestStruct::set_field); - /// - /// # #[cfg(not(feature = "no_index"))] - /// let result = engine.eval::("let a = new_ts(); a[2] = 42; a")?; - /// - /// # #[cfg(not(feature = "no_index"))] - /// assert_eq!(result.fields[2], 42); - /// # Ok(()) - /// # } - /// ``` - #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] - #[inline] - pub fn register_indexer_set_result< - T: Variant + Clone, - X: Variant + Clone, - V: Variant + Clone, - S, - >( - &mut self, - set_fn: impl RegisterNativeFunction<(Mut, X, V), (), RhaiResultOf> + SendSync + 'static, - ) -> &mut Self { - #[cfg(not(feature = "no_index"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for arrays."); - } - #[cfg(not(feature = "no_object"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for object maps."); - } - if TypeId::of::() == TypeId::of::() - || TypeId::of::() == TypeId::of::<&str>() - || TypeId::of::() == TypeId::of::() - { - panic!("Cannot register indexer for strings."); - } - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for integers."); - } - - self.register_result_fn(crate::engine::FN_IDX_SET, set_fn) - } /// Short-hand for registering both index getter and setter functions for a custom type with the [`Engine`]. /// /// Not available under both `no_index` and `no_object`. diff --git a/src/module/mod.rs b/src/module/mod.rs index 143be2a5..07d9c261 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1,7 +1,6 @@ //! Module defining external-loaded modules for Rhai. use crate::ast::FnAccess; -use crate::func::register::Mut; use crate::func::{ shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, RegisterNativeFunction, SendSync, @@ -21,6 +20,9 @@ use std::{ ops::{Add, AddAssign}, }; +#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] +use crate::func::register::Mut; + /// A type representing the namespace of a function. #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[cfg_attr(feature = "metadata", derive(serde::Serialize))] @@ -586,10 +588,10 @@ impl Module { /// /// assert_eq!(module.get_custom_type(name), Some("MyType")); /// ``` - #[inline(always)] + #[inline] #[must_use] pub fn get_custom_type(&self, key: &str) -> Option<&str> { - self.custom_types.get(key) + self.custom_types.get(key).map(|t| t.display_name.as_str()) } /// Returns `true` if this [`Module`] contains no items. diff --git a/src/types/custom_types.rs b/src/types/custom_types.rs index 4331d545..b0cb8bfd 100644 --- a/src/types/custom_types.rs +++ b/src/types/custom_types.rs @@ -3,14 +3,18 @@ use crate::Identifier; use std::{any::type_name, collections::BTreeMap, fmt}; -/// _(internals)_ A custom type. +/// _(internals)_ Information for a custom type. /// Exported under the `internals` feature only. -pub type CustomType = Identifier; +#[derive(Debug, Eq, PartialEq, Clone, Hash, Default)] +pub struct CustomTypeInfo { + /// Friendly display name of the custom type. + pub display_name: Identifier, +} /// _(internals)_ A collection of custom types. /// Exported under the `internals` feature only. #[derive(Clone, Hash, Default)] -pub struct CustomTypesCollection(BTreeMap); +pub struct CustomTypesCollection(BTreeMap); impl fmt::Debug for CustomTypesCollection { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -33,21 +37,31 @@ impl CustomTypesCollection { /// Register a custom type. #[inline(always)] pub fn add(&mut self, type_name: impl Into, name: impl Into) { - self.add_raw(type_name, name.into()); + self.add_raw( + type_name, + CustomTypeInfo { + display_name: name.into(), + }, + ); } /// Register a custom type. #[inline(always)] pub fn add_type(&mut self, name: &str) { - self.add_raw(type_name::(), name.into()); + self.add_raw( + type_name::(), + CustomTypeInfo { + display_name: name.into(), + }, + ); } /// Register a custom type. #[inline(always)] - pub fn add_raw(&mut self, type_name: impl Into, custom_type: CustomType) { + pub fn add_raw(&mut self, type_name: impl Into, custom_type: CustomTypeInfo) { self.0.insert(type_name.into(), custom_type); } /// Find a custom type. #[inline(always)] - pub fn get(&self, key: &str) -> Option<&str> { - self.0.get(key).map(CustomType::as_str) + pub fn get(&self, key: &str) -> Option<&CustomTypeInfo> { + self.0.get(key) } } diff --git a/src/types/mod.rs b/src/types/mod.rs index 6fad549e..6e2843e2 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -9,7 +9,7 @@ pub mod interner; pub mod parse_error; pub mod scope; -pub use custom_types::{CustomType, CustomTypesCollection}; +pub use custom_types::{CustomTypeInfo, CustomTypesCollection}; pub use dynamic::Dynamic; #[cfg(not(feature = "no_std"))] pub use dynamic::Instant; diff --git a/tests/build_type.rs b/tests/build_type.rs index 6d21bb9d..9fbcc1af 100644 --- a/tests/build_type.rs +++ b/tests/build_type.rs @@ -66,7 +66,7 @@ fn build_type() -> Result<(), Box> { .with_get_set("z", Self::get_z, Self::set_z); #[cfg(not(feature = "no_index"))] - builder.with_indexer_get_result(Self::get_component); + builder.with_indexer_get(Self::get_component); } } diff --git a/tests/functions.rs b/tests/functions.rs index dddb835a..8e4a7f36 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -97,7 +97,7 @@ fn test_functions_global_module() -> Result<(), Box> { if matches!(&*err, EvalAltResult::ErrorVariableNotFound(v, ..) if v == "global::ANSWER") )); - engine.register_result_fn( + engine.register_fn( "do_stuff", |context: NativeCallContext, callback: rhai::FnPtr| -> Result { callback.call_within_context(&context, ()) diff --git a/tests/get_set.rs b/tests/get_set.rs index d9065952..af1416a6 100644 --- a/tests/get_set.rs +++ b/tests/get_set.rs @@ -315,11 +315,13 @@ fn test_get_set_indexer() -> Result<(), Box> { engine .register_type_with_name::("MyMap") .register_fn("new_map", || MyMap::new()) - .register_indexer_get_result(|map: &mut MyMap, index: &str| { - map.get(index).cloned().ok_or_else(|| { - EvalAltResult::ErrorIndexNotFound(index.into(), rhai::Position::NONE).into() - }) - }) + .register_indexer_get( + |map: &mut MyMap, index: &str| -> Result<_, Box> { + map.get(index).cloned().ok_or_else(|| { + EvalAltResult::ErrorIndexNotFound(index.into(), rhai::Position::NONE).into() + }) + }, + ) .register_indexer_set(|map: &mut MyMap, index: &str, value: INT| { map.insert(index.to_string(), value); }); diff --git a/tests/modules.rs b/tests/modules.rs index a781be3f..87bc2b76 100644 --- a/tests/modules.rs +++ b/tests/modules.rs @@ -598,7 +598,7 @@ fn test_module_dynamic() -> Result<(), Box> { let mut static_modules = rhai::module_resolvers::StaticModuleResolver::new(); static_modules.insert("test", module); engine.set_module_resolver(static_modules); - engine.register_result_fn("test2", test_fn); + engine.register_fn("test2", test_fn); assert_eq!(engine.eval::(r#"test2("test", 38);"#)?, 42);