2022-01-04 15:16:20 +01:00
|
|
|
#![cfg(not(feature = "no_index"))]
|
|
|
|
#![cfg(not(feature = "no_module"))]
|
2020-08-07 02:41:06 +02:00
|
|
|
|
2020-08-03 02:49:24 +02:00
|
|
|
use rhai::plugin::*;
|
2022-10-19 06:51:52 +02:00
|
|
|
use rhai::{Engine, EvalAltResult, Scope, INT};
|
2020-08-02 09:39:16 +02:00
|
|
|
|
2020-08-20 16:11:41 +02:00
|
|
|
mod test {
|
2022-10-19 06:51:52 +02:00
|
|
|
use super::*;
|
2020-08-02 09:39:16 +02:00
|
|
|
|
2020-08-20 16:11:41 +02:00
|
|
|
#[export_module]
|
|
|
|
pub mod special_array_package {
|
|
|
|
use rhai::{Array, INT};
|
|
|
|
|
2020-09-13 16:36:24 +02:00
|
|
|
pub const MYSTIC_NUMBER: INT = 42;
|
2020-09-13 16:12:11 +02:00
|
|
|
|
2020-08-21 15:48:45 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
pub mod feature {
|
2020-09-04 09:42:31 +02:00
|
|
|
use rhai::{Array, Dynamic, EvalAltResult};
|
|
|
|
|
2020-08-21 15:48:45 +02:00
|
|
|
#[rhai_fn(get = "foo", return_raw)]
|
|
|
|
#[inline(always)]
|
2021-03-03 15:49:29 +01:00
|
|
|
pub fn foo(array: &mut Array) -> Result<Dynamic, Box<EvalAltResult>> {
|
2020-08-21 15:48:45 +02:00
|
|
|
Ok(array[0].clone())
|
|
|
|
}
|
2020-08-20 16:11:41 +02:00
|
|
|
}
|
2020-08-21 15:48:45 +02:00
|
|
|
|
2020-09-19 12:18:40 +02:00
|
|
|
pub fn hash(_text: String) -> INT {
|
|
|
|
42
|
|
|
|
}
|
2020-09-20 08:23:14 +02:00
|
|
|
pub fn hash2(_text: &str) -> INT {
|
|
|
|
42
|
|
|
|
}
|
2020-09-19 12:18:40 +02:00
|
|
|
|
2020-09-04 05:57:40 +02:00
|
|
|
#[rhai_fn(name = "test", name = "hi")]
|
2020-08-20 16:11:41 +02:00
|
|
|
pub fn len(array: &mut Array, mul: INT) -> INT {
|
|
|
|
(array.len() as INT) * mul
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "+")]
|
|
|
|
pub fn funky_add(x: INT, y: INT) -> INT {
|
|
|
|
x / 2 + y * 2
|
|
|
|
}
|
2021-05-15 05:41:42 +02:00
|
|
|
#[rhai_fn(name = "no_effect", set = "no_effect", pure)]
|
|
|
|
pub fn no_effect(array: &mut Array, value: INT) {
|
|
|
|
// array is not modified
|
2022-09-25 06:24:03 +02:00
|
|
|
println!("Array = {array:?}, Value = {value}");
|
2021-05-13 04:34:24 +02:00
|
|
|
}
|
2020-08-16 17:41:59 +02:00
|
|
|
}
|
2020-08-02 09:39:16 +02:00
|
|
|
}
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
macro_rules! gen_unary_functions {
|
|
|
|
($op_name:ident = $op_fn:ident ( $($arg_type:ident),+ ) -> $return_type:ident) => {
|
|
|
|
mod $op_name { $(
|
2020-10-03 05:42:54 +02:00
|
|
|
#[allow(non_snake_case)]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub mod $arg_type {
|
|
|
|
use super::super::*;
|
|
|
|
|
2020-08-16 17:41:59 +02:00
|
|
|
#[export_fn(name="test")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn single(x: $arg_type) -> $return_type {
|
|
|
|
super::super::$op_fn(x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)* }
|
|
|
|
}
|
2020-08-02 12:53:25 +02:00
|
|
|
}
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
macro_rules! reg_functions {
|
|
|
|
($mod_name:ident += $op_name:ident :: $func:ident ( $($arg_type:ident),+ )) => {
|
|
|
|
$(register_exported_fn!($mod_name, stringify!($op_name), $op_name::$arg_type::$func);)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 14:50:14 +01:00
|
|
|
fn make_greeting(n: impl std::fmt::Display) -> String {
|
2022-08-11 13:01:23 +02:00
|
|
|
format!("{n} kitties")
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gen_unary_functions!(greet = make_greeting(INT, bool, char) -> String);
|
|
|
|
|
2022-08-30 07:56:25 +02:00
|
|
|
macro_rules! expand_enum {
|
|
|
|
($module:ident : $typ:ty => $($variant:ident),+) => {
|
|
|
|
#[export_module]
|
|
|
|
pub mod $module {
|
|
|
|
$(
|
2022-09-03 05:29:29 +02:00
|
|
|
#[allow(non_upper_case_globals)]
|
2022-08-30 07:56:25 +02:00
|
|
|
pub const $variant: $typ = <$typ>::$variant;
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
|
|
pub enum MyEnum {
|
|
|
|
Foo,
|
|
|
|
Bar,
|
|
|
|
Baz,
|
|
|
|
Hello,
|
|
|
|
World,
|
|
|
|
}
|
|
|
|
|
|
|
|
expand_enum! { my_enum_module: MyEnum => Foo, Bar, Baz, Hello, World }
|
|
|
|
|
2020-08-02 09:39:16 +02:00
|
|
|
#[test]
|
2020-08-02 12:53:25 +02:00
|
|
|
fn test_plugins_package() -> Result<(), Box<EvalAltResult>> {
|
2020-08-02 09:39:16 +02:00
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
2020-08-21 15:48:45 +02:00
|
|
|
let mut m = Module::new();
|
2020-09-13 16:12:11 +02:00
|
|
|
combine_with_exported_module!(&mut m, "test", test::special_array_package);
|
2022-08-30 07:56:25 +02:00
|
|
|
combine_with_exported_module!(&mut m, "enum", my_enum_module);
|
2020-12-23 03:08:43 +01:00
|
|
|
engine.register_global_module(m.into());
|
2020-08-02 09:39:16 +02:00
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
reg_functions!(engine += greet::single(INT, bool, char));
|
|
|
|
|
2022-03-27 15:49:34 +02:00
|
|
|
assert_eq!(engine.eval::<INT>("MYSTIC_NUMBER")?, 42);
|
|
|
|
|
2020-08-19 07:39:20 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-13 04:34:24 +02:00
|
|
|
{
|
|
|
|
assert_eq!(engine.eval::<INT>("let a = [1, 2, 3]; a.foo")?, 1);
|
2021-08-06 08:46:27 +02:00
|
|
|
engine.run("const A = [1, 2, 3]; A.no_effect(42);")?;
|
|
|
|
engine.run("const A = [1, 2, 3]; A.no_effect = 42;")?;
|
2021-05-13 04:34:24 +02:00
|
|
|
|
|
|
|
assert!(
|
2023-04-10 17:23:59 +02:00
|
|
|
matches!(*engine.run("const A = [1, 2, 3]; A.test(42);").unwrap_err(),
|
2022-10-27 16:08:47 +02:00
|
|
|
EvalAltResult::ErrorNonPureMethodCallOnConstant(x, ..) if x == "test")
|
2021-05-13 04:34:24 +02:00
|
|
|
)
|
|
|
|
}
|
2020-08-19 07:39:20 +02:00
|
|
|
|
2020-09-19 12:18:40 +02:00
|
|
|
assert_eq!(engine.eval::<INT>(r#"hash("hello")"#)?, 42);
|
2020-09-20 08:23:14 +02:00
|
|
|
assert_eq!(engine.eval::<INT>(r#"hash2("hello")"#)?, 42);
|
2020-09-04 05:57:40 +02:00
|
|
|
assert_eq!(engine.eval::<INT>("let a = [1, 2, 3]; test(a, 2)")?, 6);
|
|
|
|
assert_eq!(engine.eval::<INT>("let a = [1, 2, 3]; hi(a, 2)")?, 6);
|
2020-08-16 17:41:59 +02:00
|
|
|
assert_eq!(engine.eval::<INT>("let a = [1, 2, 3]; test(a, 2)")?, 6);
|
2020-08-02 12:53:25 +02:00
|
|
|
assert_eq!(
|
2020-08-16 17:41:59 +02:00
|
|
|
engine.eval::<String>("let a = [1, 2, 3]; greet(test(a, 2))")?,
|
2020-08-02 12:53:25 +02:00
|
|
|
"6 kitties"
|
|
|
|
);
|
2022-09-03 16:07:36 +02:00
|
|
|
assert_eq!(engine.eval::<INT>("2 + 2")?, 4);
|
|
|
|
|
|
|
|
engine.set_fast_operators(false);
|
|
|
|
assert_eq!(engine.eval::<INT>("2 + 2")?, 5);
|
2020-08-02 09:39:16 +02:00
|
|
|
|
2020-12-23 03:08:43 +01:00
|
|
|
engine.register_static_module("test", exported_module!(test::special_array_package).into());
|
2020-09-13 16:12:11 +02:00
|
|
|
|
2020-11-16 14:14:32 +01:00
|
|
|
assert_eq!(engine.eval::<INT>("test::MYSTIC_NUMBER")?, 42);
|
2020-09-13 16:12:11 +02:00
|
|
|
|
2020-08-02 09:39:16 +02:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-01-23 02:37:27 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_plugins_parameters() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
#[export_module]
|
|
|
|
mod rhai_std {
|
|
|
|
pub fn noop(_: &str) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
|
|
|
let std = exported_module!(rhai_std);
|
|
|
|
|
|
|
|
engine.register_static_module("std", std.into());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
engine.eval::<String>(
|
|
|
|
r#"
|
|
|
|
let s = "hello";
|
|
|
|
std::noop(s);
|
|
|
|
s
|
|
|
|
"#
|
|
|
|
)?,
|
|
|
|
"hello"
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2022-10-19 06:51:52 +02:00
|
|
|
|
|
|
|
#[cfg(target_pointer_width = "64")]
|
|
|
|
mod handle {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
|
|
|
pub struct WorldHandle(usize);
|
|
|
|
pub type World = Vec<i64>;
|
|
|
|
|
|
|
|
impl From<&mut World> for WorldHandle {
|
|
|
|
fn from(world: &mut World) -> Self {
|
|
|
|
Self::new(world)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsMut<World> for WorldHandle {
|
|
|
|
fn as_mut(&mut self) -> &mut World {
|
|
|
|
unsafe { std::mem::transmute(self.0) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl WorldHandle {
|
|
|
|
pub fn new(world: &mut World) -> Self {
|
|
|
|
Self(unsafe { std::mem::transmute(world) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[export_module]
|
|
|
|
pub mod handle_module {
|
|
|
|
pub type Handle = WorldHandle;
|
|
|
|
|
|
|
|
#[rhai_fn(get = "len")]
|
|
|
|
pub fn len(world: &mut Handle) -> INT {
|
|
|
|
world.as_mut().len() as INT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_handle() -> Result<(), Box<EvalAltResult>> {
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
|
|
|
engine.register_global_module(exported_module!(handle_module).into());
|
|
|
|
|
|
|
|
let mut scope = Scope::new();
|
|
|
|
|
|
|
|
let world: &mut World = &mut vec![42];
|
|
|
|
scope.push("world", WorldHandle::from(world));
|
|
|
|
|
2022-10-20 07:01:36 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2022-10-19 06:51:52 +02:00
|
|
|
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "world.len")?, 1);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|