From 2b0aacde23780e7399fcb53a6b712074203be67a Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 24 Jul 2020 23:16:54 +0800 Subject: [PATCH] Fix Module::set_indexer_set_fn. --- RELEASES.md | 1 + src/engine.rs | 4 ++-- src/module.rs | 42 ++++++++++++++++++++++++++++++++++++++---- tests/functions.rs | 14 ++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 8ba7d09c..22aae65d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -18,6 +18,7 @@ New features * Anonymous functions in the syntax of a closure, e.g. `|x, y, z| x + y - z`. * Custom syntax now works even without the `internals` feature. * Currying of function pointers is supported via the `curry` keyword. +* `Module::set_indexer_get_set_fn` is added as a shorthand of both `Module::set_indexer_get_fn` and `Module::set_indexer_set_fn`. Breaking changes ---------------- diff --git a/src/engine.rs b/src/engine.rs index cb7234d3..f34cb7ca 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -11,7 +11,7 @@ use crate::parser::{Expr, FnAccess, ImmutableString, ReturnType, ScriptFnDef, St use crate::r#unsafe::unsafe_cast_var_name_to_lifetime; use crate::result::EvalAltResult; use crate::scope::{EntryType as ScopeEntryType, Scope}; -use crate::syntax::{CustomSyntax, EvalContext, Expression}; +use crate::syntax::{CustomSyntax, EvalContext}; use crate::token::Position; use crate::utils::StaticVec; @@ -1020,7 +1020,7 @@ impl Engine { map.entry(index).or_insert(Default::default()).into() } else { let index = idx - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| EvalAltResult::ErrorStringIndexExpr(idx_pos))?; map.get_mut(index.as_str()) diff --git a/src/module.rs b/src/module.rs index 7216c248..11787e1c 100644 --- a/src/module.rs +++ b/src/module.rs @@ -738,18 +738,18 @@ impl Module { /// }); /// assert!(module.contains_fn(hash)); /// ``` - pub fn set_indexer_set_fn( + pub fn set_indexer_set_fn( &mut self, - func: impl Fn(&mut A, B, A) -> FuncReturn<()> + SendSync + 'static, + func: impl Fn(&mut A, B, C) -> FuncReturn<()> + SendSync + 'static, ) -> u64 { let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| { let b = mem::take(args[1]).cast::(); - let c = mem::take(args[2]).cast::(); + let c = mem::take(args[2]).cast::(); let a = args[0].downcast_mut::().unwrap(); func(a, b, c).map(Dynamic::from) }; - let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; self.set_fn( FN_IDX_SET, Public, @@ -758,6 +758,40 @@ impl Module { ) } + /// Set a pair of Rust index getter and setter functions, returning both hash keys. + /// This is a shorthand for `set_indexer_get_fn` and `set_indexer_set_fn`. + /// + /// If there are similar existing Rust functions, they are replaced. + /// + /// # Examples + /// + /// ``` + /// use rhai::{Module, ImmutableString}; + /// + /// let mut module = Module::new(); + /// let (hash_get, hash_set) = module.set_indexer_get_set_fn( + /// |x: &mut i64, y: ImmutableString| { + /// Ok(*x + y.len() as i64) + /// }, + /// |x: &mut i64, y: ImmutableString, value: i64| { + /// *x = y.len() as i64 + value; + /// Ok(()) + /// } + /// ); + /// assert!(module.contains_fn(hash_get)); + /// assert!(module.contains_fn(hash_set)); + /// ``` + pub fn set_indexer_get_set_fn( + &mut self, + getter: impl Fn(&mut A, B) -> FuncReturn + SendSync + 'static, + setter: impl Fn(&mut A, B, T) -> FuncReturn<()> + SendSync + 'static, + ) -> (u64, u64) { + ( + self.set_indexer_get_fn(getter), + self.set_indexer_set_fn(setter), + ) + } + /// 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. diff --git a/tests/functions.rs b/tests/functions.rs index 3c0a080b..78d20fa3 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -104,5 +104,19 @@ fn test_function_pointers() -> Result<(), Box> { 42 ); + #[cfg(not(feature = "no_object"))] + assert_eq!( + engine.eval::( + r#" + fn foo(x) { this.data += x; } + + let x = #{ data: 40, action: Fn("foo") }; + x.action(2); + x.data + "# + )?, + 42 + ); + Ok(()) }