Fix Module::set_indexer_set_fn.
This commit is contained in:
parent
bff266d4e1
commit
2b0aacde23
@ -18,6 +18,7 @@ New features
|
|||||||
* Anonymous functions in the syntax of a closure, e.g. `|x, y, z| x + y - z`.
|
* 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.
|
* Custom syntax now works even without the `internals` feature.
|
||||||
* Currying of function pointers is supported via the `curry` keyword.
|
* 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
|
Breaking changes
|
||||||
----------------
|
----------------
|
||||||
|
@ -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::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
use crate::syntax::{CustomSyntax, EvalContext, Expression};
|
use crate::syntax::{CustomSyntax, EvalContext};
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
use crate::utils::StaticVec;
|
use crate::utils::StaticVec;
|
||||||
|
|
||||||
@ -1020,7 +1020,7 @@ impl Engine {
|
|||||||
map.entry(index).or_insert(Default::default()).into()
|
map.entry(index).or_insert(Default::default()).into()
|
||||||
} else {
|
} else {
|
||||||
let index = idx
|
let index = idx
|
||||||
.downcast_ref::<String>()
|
.downcast_ref::<ImmutableString>()
|
||||||
.ok_or_else(|| EvalAltResult::ErrorStringIndexExpr(idx_pos))?;
|
.ok_or_else(|| EvalAltResult::ErrorStringIndexExpr(idx_pos))?;
|
||||||
|
|
||||||
map.get_mut(index.as_str())
|
map.get_mut(index.as_str())
|
||||||
|
@ -738,18 +738,18 @@ impl Module {
|
|||||||
/// });
|
/// });
|
||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_indexer_set_fn<A: Variant + Clone, B: Variant + Clone>(
|
pub fn set_indexer_set_fn<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: impl Fn(&mut A, B, A) -> FuncReturn<()> + SendSync + 'static,
|
func: impl Fn(&mut A, B, C) -> FuncReturn<()> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<A>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
let a = args[0].downcast_mut::<A>().unwrap();
|
let a = args[0].downcast_mut::<A>().unwrap();
|
||||||
|
|
||||||
func(a, b, c).map(Dynamic::from)
|
func(a, b, c).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
FN_IDX_SET,
|
FN_IDX_SET,
|
||||||
Public,
|
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<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
||||||
|
&mut self,
|
||||||
|
getter: impl Fn(&mut A, B) -> FuncReturn<T> + 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.
|
/// 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.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
|
@ -104,5 +104,19 @@ fn test_function_pointers() -> Result<(), Box<EvalAltResult>> {
|
|||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(
|
||||||
|
r#"
|
||||||
|
fn foo(x) { this.data += x; }
|
||||||
|
|
||||||
|
let x = #{ data: 40, action: Fn("foo") };
|
||||||
|
x.action(2);
|
||||||
|
x.data
|
||||||
|
"#
|
||||||
|
)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user