Struct casbin::rhai::Engine

source ·
pub struct Engine { /* private fields */ }
Expand description

Rhai main scripting engine.

§Thread Safety

Engine is re-entrant.

Currently, Engine is neither Send nor Sync. Use the sync feature to make it Send + Sync.

§Example

use rhai::Engine;

let engine = Engine::new();

let result = engine.eval::<i64>("40 + 2")?;

println!("Answer: {result}");   // prints 42

Implementations§

source§

impl Engine

source

pub fn eval<T>(&self, script: &str) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate a string as a script, returning the result value or an error.

§Example
use rhai::Engine;

let engine = Engine::new();

assert_eq!(engine.eval::<i64>("40 + 2")?, 42);
source

pub fn eval_with_scope<T>( &self, scope: &mut Scope<'_>, script: &str ) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate a string as a script with own scope, returning the result value or an error.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions.

This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);

assert_eq!(engine.eval_with_scope::<i64>(&mut scope, "x += 2; x")?, 42);
assert_eq!(engine.eval_with_scope::<i64>(&mut scope, "x += 2; x")?, 44);

// The variable in the scope is modified
assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 44);
source

pub fn eval_expression<T>(&self, script: &str) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate a string containing an expression, returning the result value or an error.

§Example
use rhai::Engine;

let engine = Engine::new();

assert_eq!(engine.eval_expression::<i64>("40 + 2")?, 42);
source

pub fn eval_expression_with_scope<T>( &self, scope: &mut Scope<'_>, script: &str ) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate a string containing an expression with own scope, returning the result value or an error.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);

assert_eq!(engine.eval_expression_with_scope::<i64>(&mut scope, "x + 2")?, 42);
source

pub fn eval_ast<T>(&self, ast: &AST) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate an AST, returning the result value or an error.

§Example
use rhai::Engine;

let engine = Engine::new();

// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("40 + 2")?;

// Evaluate it
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
source

pub fn eval_ast_with_scope<T>( &self, scope: &mut Scope<'_>, ast: &AST ) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate an AST with own scope, returning the result value or an error.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);

// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("x += 2; x")?;

// Evaluate it
assert_eq!(engine.eval_ast_with_scope::<i64>(&mut scope, &ast)?, 42);
assert_eq!(engine.eval_ast_with_scope::<i64>(&mut scope, &ast)?, 44);

// The variable in the scope is modified
assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 44);
source§

impl Engine

source

pub fn run(&self, script: &str) -> Result<(), Box<EvalAltResult>>

Evaluate a string as a script.

§Example
use rhai::Engine;

let engine = Engine::new();

engine.run("print(40 + 2);")?;
source

pub fn run_with_scope( &self, scope: &mut Scope<'_>, script: &str ) -> Result<(), Box<EvalAltResult>>

Evaluate a string as a script with own scope.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions.

This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);

engine.run_with_scope(&mut scope, "x += 2; print(x);")?;

// The variable in the scope is modified
assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 42);
source

pub fn run_ast(&self, ast: &AST) -> Result<(), Box<EvalAltResult>>

Evaluate an AST.

§Example
use rhai::Engine;

let engine = Engine::new();

// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("print(40 + 2);")?;

// Evaluate it
engine.run_ast(&ast)?;
source

pub fn run_ast_with_scope( &self, scope: &mut Scope<'_>, ast: &AST ) -> Result<(), Box<EvalAltResult>>

Evaluate an AST with own scope.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);

// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("x += 2; x")?;

// Evaluate it
engine.run_ast_with_scope(&mut scope, &ast)?;

// The variable in the scope is modified
assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 42);
source§

impl Engine

source

pub fn compile(&self, script: impl AsRef<str>) -> Result<AST, ParseError>

Compile a string into an AST, which can be used later for evaluation.

§Example
use rhai::Engine;

let engine = Engine::new();

// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("40 + 2")?;

for _ in 0..42 {
    assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
}
source

pub fn compile_with_scope( &self, scope: &Scope<'_>, script: impl AsRef<str> ) -> Result<AST, ParseError>

Compile a string into an AST using own scope, which can be used later for evaluation.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions. This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope, OptimizationLevel};

let mut engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 42_i64);   // 'x' is a constant

// Compile a script to an AST and store it for later evaluation.
// Notice that `Full` optimization is on, so constants are folded
// into function calls and operators.
let ast = engine.compile_with_scope(&mut scope,
            "if x > 40 { x } else { 0 }"    // all 'x' are replaced with 42
)?;

// Normally this would have failed because no scope is passed into the 'eval_ast'
// call and so the variable 'x' does not exist.  Here, it passes because the script
// has been optimized and all references to 'x' are already gone.
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
source

pub fn compile_scripts_with_scope<S>( &self, scope: &Scope<'_>, scripts: impl AsRef<[S]> ) -> Result<AST, ParseError>
where S: AsRef<str>,

When passed a list of strings, first join the strings into one large script, and then compile them into an AST using own scope, which can be used later for evaluation.

The scope is useful for passing constants into the script for optimization when using [OptimizationLevel::Full][crate::OptimizationLevel::Full].

§Note

All strings are simply parsed one after another with nothing inserted in between, not even a newline or space.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions. This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope, OptimizationLevel};

let mut engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 42_i64);   // 'x' is a constant

// Compile a script made up of script segments to an AST and store it for later evaluation.
// Notice that `Full` optimization is on, so constants are folded
// into function calls and operators.
let ast = engine.compile_scripts_with_scope(&mut scope, &[
            "if x > 40",            // all 'x' are replaced with 42
            "{ x } el",
            "se { 0 }"              // segments do not need to be valid scripts!
])?;

// Normally this would have failed because no scope is passed into the 'eval_ast'
// call and so the variable 'x' does not exist.  Here, it passes because the script
// has been optimized and all references to 'x' are already gone.
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
source

pub fn compile_expression( &self, script: impl AsRef<str> ) -> Result<AST, ParseError>

Compile a string containing an expression into an AST, which can be used later for evaluation.

§Example
use rhai::Engine;

let engine = Engine::new();

// Compile a script to an AST and store it for later evaluation
let ast = engine.compile_expression("40 + 2")?;

for _ in 0..42 {
    assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
}
source

pub fn compile_expression_with_scope( &self, scope: &Scope<'_>, script: impl AsRef<str> ) -> Result<AST, ParseError>

Compile a string containing an expression into an AST using own scope, which can be used later for evaluation.

§Example
use rhai::{Engine, Scope, OptimizationLevel};

let mut engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 10_i64);   // 'x' is a constant

// Compile a script to an AST and store it for later evaluation.
let ast = engine.compile_expression_with_scope(&mut scope,
            "2 + (x + x) * 2"    // all 'x' are replaced with 10
)?;

// Normally this would have failed because no scope is passed into the 'eval_ast'
// call and so the variable 'x' does not exist.  Here, it passes because the script
// has been optimized and all references to 'x' are already gone.
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
source§

impl Engine

source

pub fn parse_json( &self, json: impl AsRef<str>, has_null: bool ) -> Result<BTreeMap<SmartString<LazyCompact>, Dynamic>, Box<EvalAltResult>>

Parse a JSON string into an object map.

This is a light-weight alternative to using, say, serde_json to deserialize the JSON.

Not available under no_object.

The JSON string must be an object hash. It cannot be a simple primitive value.

Set has_null to true in order to map null values to (). Setting it to false causes a syntax error for any null value.

JSON sub-objects are handled transparently.

This function can be used together with format_map_as_json to work with JSON texts without using the serde_json crate (which is heavy).

§Example
use rhai::{Engine, Map};

let engine = Engine::new();

let map = engine.parse_json(r#"
{
    "a": 123,
    "b": 42,
    "c": {
        "x": false,
        "y": true,
        "z": '$'
    },
    "d": null
}"#, true)?;

assert_eq!(map.len(), 4);
assert_eq!(map["a"].as_int().expect("a should exist"), 123);
assert_eq!(map["b"].as_int().expect("b should exist"), 42);
assert_eq!(map["d"].as_unit().expect("d should exist"), ());

let c = map["c"].read_lock::<Map>().expect("c should exist");
assert_eq!(c["x"].as_bool().expect("x should be bool"), false);
assert_eq!(c["y"].as_bool().expect("y should be bool"), true);
assert_eq!(c["z"].as_char().expect("z should be char"), '$');
source§

impl Engine

source

pub fn compile_file(&self, path: PathBuf) -> Result<AST, Box<EvalAltResult>>

Compile a script file into an AST, which can be used later for evaluation.

Not available under no_std or WASM.

§Example
use rhai::Engine;

let engine = Engine::new();

// Compile a script file to an AST and store it for later evaluation.
// Notice that a PathBuf is required which can easily be constructed from a string.
let ast = engine.compile_file("script.rhai".into())?;

for _ in 0..42 {
    engine.eval_ast::<i64>(&ast)?;
}
source

pub fn compile_file_with_scope( &self, scope: &Scope<'_>, path: PathBuf ) -> Result<AST, Box<EvalAltResult>>

Compile a script file into an AST using own scope, which can be used later for evaluation.

Not available under no_std or WASM.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions.

This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope, OptimizationLevel};

let mut engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 42_i64);   // 'x' is a constant

// Compile a script to an AST and store it for later evaluation.
// Notice that a PathBuf is required which can easily be constructed from a string.
let ast = engine.compile_file_with_scope(&scope, "script.rhai".into())?;

let result = engine.eval_ast::<i64>(&ast)?;
source

pub fn eval_file<T>(&self, path: PathBuf) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate a script file, returning the result value or an error.

Not available under no_std or WASM.

§Example
use rhai::Engine;

let engine = Engine::new();

// Notice that a PathBuf is required which can easily be constructed from a string.
let result = engine.eval_file::<i64>("script.rhai".into())?;
source

pub fn eval_file_with_scope<T>( &self, scope: &mut Scope<'_>, path: PathBuf ) -> Result<T, Box<EvalAltResult>>
where T: Variant + Clone,

Evaluate a script file with own scope, returning the result value or an error.

Not available under no_std or WASM.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions.

This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 42_i64);

// Notice that a PathBuf is required which can easily be constructed from a string.
let result = engine.eval_file_with_scope::<i64>(&mut scope, "script.rhai".into())?;
source

pub fn run_file(&self, path: PathBuf) -> Result<(), Box<EvalAltResult>>

Evaluate a file.

Not available under no_std or WASM.

§Example
use rhai::Engine;

let engine = Engine::new();

// Notice that a PathBuf is required which can easily be constructed from a string.
engine.run_file("script.rhai".into())?;
source

pub fn run_file_with_scope( &self, scope: &mut Scope<'_>, path: PathBuf ) -> Result<(), Box<EvalAltResult>>

Evaluate a file with own scope.

Not available under no_std or WASM.

§Constants Propagation

If not [OptimizationLevel::None][crate::OptimizationLevel::None], constants defined within the scope are propagated throughout the script including functions.

This allows functions to be optimized based on dynamic global constants.

§Example
use rhai::{Engine, Scope};

let engine = Engine::new();

// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 42_i64);

// Notice that a PathBuf is required which can easily be constructed from a string.
engine.run_file_with_scope(&mut scope, "script.rhai".into())?;
source§

impl Engine

source

pub fn register_fn<A, const N: usize, const X: bool, R, const F: bool, FUNC>( &mut self, name: impl AsRef<str> + Into<SmartString<LazyCompact>>, func: FUNC ) -> &mut Engine
where A: 'static, R: Variant + Clone, FUNC: RhaiNativeFunc<A, N, X, R, F> + SendSync + 'static,

Register a custom function with the Engine.

§Assumptions
  • Accessibility: The function namespace is FnNamespace::Global.

  • Purity: The function is assumed to be pure unless it is a property setter or an index setter.

  • Volatility: The function is assumed to be non-volatile – i.e. it guarantees the same result for the same input(s).

§Example
use rhai::Engine;

// Normal function
fn add(x: i64, y: i64) -> i64 {
    x + y
}

let mut engine = Engine::new();

engine.register_fn("add", add);

assert_eq!(engine.eval::<i64>("add(40, 2)")?, 42);

// You can also register a closure.
engine.register_fn("sub", |x: i64, y: i64| x - y );

assert_eq!(engine.eval::<i64>("sub(44, 2)")?, 42);
source

pub fn register_raw_fn<T>( &mut self, name: impl AsRef<str> + Into<SmartString<LazyCompact>>, arg_types: impl AsRef<[TypeId]>, func: impl Fn(NativeCallContext<'_>, &mut [&mut Dynamic]) -> Result<T, Box<EvalAltResult>> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone,

Register a function of the Engine.

§WARNING - Low Level API

This function is very low level. It takes a list of TypeId’s indicating the actual types of the parameters.

§Arguments

Arguments are simply passed in as a mutable array of &mut Dynamic. The arguments are guaranteed to be of the correct types matching the TypeId’s.

To access a primary argument value (i.e. cloning is cheap), use: args[n].as_xxx().unwrap()

To access an argument value and avoid cloning, use args[n].take().cast::<T>(). Notice that this will consume the argument, replacing it with ().

To access the first mutable parameter, use args.get_mut(0).unwrap()

source

pub fn register_type<T>(&mut self) -> &mut Engine
where T: Variant + Clone,

Register a custom type for use with the Engine. The type must implement Clone.

§Example
#[derive(Debug, Clone, Eq, PartialEq)]
struct TestStruct {
    field: i64
}

impl TestStruct {
    fn new() -> Self {
        Self { field: 1 }
    }
    fn update(&mut self, offset: i64) {
        self.field += offset;
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine
    .register_type::<TestStruct>()
    .register_fn("new_ts", TestStruct::new)
    // Use `register_fn` to register methods on the type.
    .register_fn("update", TestStruct::update);

assert_eq!(
    engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?,
    TestStruct { field: 42 }
);
source

pub fn register_type_with_name<T>(&mut self, name: &str) -> &mut Engine
where T: Variant + Clone,

Register a custom type for use with the Engine, with a pretty-print name for the type_of function. The type must implement Clone.

§Example
#[derive(Clone)]
struct TestStruct {
    field: i64
}

impl TestStruct {
    fn new() -> Self {
        Self { field: 1 }
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine
    .register_type::<TestStruct>()
    .register_fn("new_ts", TestStruct::new);

assert_eq!(
    engine.eval::<String>("let x = new_ts(); type_of(x)")?,
    "rust_out::TestStruct"
);

// Re-register the custom type with a name.
engine.register_type_with_name::<TestStruct>("Hello");

assert_eq!(
    engine.eval::<String>("let x = new_ts(); type_of(x)")?,
    "Hello"
);
source

pub fn register_type_with_name_raw( &mut self, type_path: impl Into<SmartString<LazyCompact>>, name: impl Into<SmartString<LazyCompact>> ) -> &mut Engine

Register a custom type for use with the Engine, with a pretty-print name for the type_of function. The type must implement Clone.

§WARNING - Low Level API

This function is low level.

source

pub fn register_iterator<T>(&mut self) -> &mut Engine
where T: Variant + Clone + IntoIterator, <T as IntoIterator>::Item: Variant + Clone,

Register a type iterator for an iterable type with the Engine. This is an advanced API.

source

pub fn register_iterator_result<T, R>(&mut self) -> &mut Engine
where T: Variant + Clone + IntoIterator<Item = Result<R, Box<EvalAltResult>>>, R: Variant + Clone,

Register a fallible type iterator for an iterable type with the Engine. This is an advanced API.

source

pub fn register_get<T, const X: bool, R, const F: bool>( &mut self, name: impl AsRef<str>, get_fn: impl RhaiNativeFunc<(Mut<T>,), 1, X, R, F> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, R: Variant + Clone,

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
#[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) -> i64  {
        self.field
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine
    .register_type::<TestStruct>()
    .register_fn("new_ts", TestStruct::new)
    // Register a getter on a property (notice it doesn't have to be the same name).
    .register_get("xyz", TestStruct::get_field);

assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
source

pub fn register_set<T, const X: bool, R, const F: bool>( &mut self, name: impl AsRef<str>, set_fn: impl RhaiNativeFunc<(Mut<T>, R), 2, X, (), F> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, R: Variant + Clone,

Register a setter function for a member of a registered type with the Engine.

Not available under no_object.

§Example
#[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) {
        self.field = new_val;
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine
    .register_type::<TestStruct>()
    .register_fn("new_ts", TestStruct::new)
    // Register a setter on a property (notice it doesn't have to be the same name)
    .register_set("xyz", TestStruct::set_field);

// Notice that, with a getter, there is no way to get the property value
assert_eq!(
    engine.eval::<TestStruct>("let a = new_ts(); a.xyz = 42; a")?,
    TestStruct { field: 42 }
);
source

pub fn register_get_set<T, const X1: bool, const X2: bool, R, const F1: bool, const F2: bool>( &mut self, name: impl AsRef<str>, get_fn: impl RhaiNativeFunc<(Mut<T>,), 1, X1, R, F1> + SendSync + 'static, set_fn: impl RhaiNativeFunc<(Mut<T>, R), 2, X2, (), F2> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, R: Variant + Clone,

Short-hand for registering both getter and setter functions of a registered type with the Engine.

All function signatures must start with &mut self and not &self.

Not available under no_object.

§Example
#[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) -> i64 {
        self.field
    }
    fn set_field(&mut self, new_val: i64) {
        self.field = new_val;
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine
    .register_type::<TestStruct>()
    .register_fn("new_ts", TestStruct::new)
    // Register both a getter and a setter on a property
    // (notice it doesn't have to be the same name)
    .register_get_set("xyz", TestStruct::get_field, TestStruct::set_field);

assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz = 42; a.xyz")?, 42);
source

pub fn register_indexer_get<T, IDX, const X: bool, R, const F: bool>( &mut self, get_fn: impl RhaiNativeFunc<(Mut<T>, IDX), 2, X, R, F> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, IDX: Variant + Clone, R: Variant + Clone,

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, Map, String, ImmutableString, &str or INT. Indexers for arrays, object maps, strings and integers cannot be registered.

§Example
#[derive(Clone)]
struct TestStruct {
    fields: Vec<i64>
}

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) -> i64 {
        self.fields[index as usize]
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine.register_type::<TestStruct>();

engine
    .register_fn("new_ts", TestStruct::new)
    // Register an indexer.
    .register_indexer_get(TestStruct::get_field);

assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
source

pub fn register_indexer_set<T, IDX, const X: bool, R, const F: bool>( &mut self, set_fn: impl RhaiNativeFunc<(Mut<T>, IDX, R), 3, X, (), F> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, IDX: Variant + Clone, R: Variant + Clone,

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, Map, String, ImmutableString, &str or INT. Indexers for arrays, object maps, strings and integers cannot be registered.

§Example
#[derive(Clone)]
struct TestStruct {
    fields: Vec<i64>
}

impl TestStruct {
    fn new() -> Self {
        Self { fields: vec![1, 2, 3, 4, 5] }
    }
    fn set_field(&mut self, index: i64, value: i64) {
        self.fields[index as usize] = value;
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine.register_type::<TestStruct>();

engine
    .register_fn("new_ts", TestStruct::new)
    // Register an indexer.
    .register_indexer_set(TestStruct::set_field);

let result = engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?;

assert_eq!(result.fields[2], 42);
source

pub fn register_indexer_get_set<T, IDX, const X1: bool, const X2: bool, R, const F1: bool, const F2: bool>( &mut self, get_fn: impl RhaiNativeFunc<(Mut<T>, IDX), 2, X1, R, F1> + SendSync + 'static, set_fn: impl RhaiNativeFunc<(Mut<T>, IDX, R), 3, X2, (), F2> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, IDX: Variant + Clone, R: Variant + Clone,

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.

§Panics

Panics if the type is Array, Map, String, ImmutableString, &str or INT. Indexers for arrays, object maps, strings and integers cannot be registered.

§Example
#[derive(Clone)]
struct TestStruct {
    fields: Vec<i64>
}

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) -> i64 {
        self.fields[index as usize]
    }
    fn set_field(&mut self, index: i64, value: i64) {
        self.fields[index as usize] = value;
    }
}

use rhai::Engine;

let mut engine = Engine::new();

// Register API for the custom type.
engine.register_type::<TestStruct>();

engine
    .register_fn("new_ts", TestStruct::new)
    // Register an indexer.
    .register_indexer_get_set(TestStruct::get_field, TestStruct::set_field);

assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?, 42);
source

pub fn register_global_module(&mut self, module: Arc<Module>) -> &mut Engine

Register a shared Module into the global namespace of Engine.

All functions and type iterators are automatically available to scripts without namespace qualifications.

Sub-modules and variables are ignored.

When searching for functions, modules loaded later are preferred. In other words, loaded modules are searched in reverse order.

source§

impl Engine

source

pub const fn allow_if_expression(&self) -> bool

Is if-expression allowed? Default is true.

source

pub fn set_allow_if_expression(&mut self, enable: bool) -> &mut Engine

Set whether if-expression is allowed.

source

pub const fn allow_switch_expression(&self) -> bool

Is switch expression allowed? Default is true.

source

pub fn set_allow_switch_expression(&mut self, enable: bool) -> &mut Engine

Set whether switch expression is allowed.

source

pub const fn allow_loop_expressions(&self) -> bool

Are loop expressions allowed? Default is true.

source

pub fn set_allow_loop_expressions(&mut self, enable: bool) -> &mut Engine

Set whether loop expressions are allowed.

source

pub const fn allow_statement_expression(&self) -> bool

Is statement-expression allowed? Default is true.

source

pub fn set_allow_statement_expression(&mut self, enable: bool) -> &mut Engine

Set whether statement-expression is allowed.

source

pub const fn allow_looping(&self) -> bool

Is looping allowed? Default is true.

source

pub fn set_allow_looping(&mut self, enable: bool) -> &mut Engine

Set whether looping is allowed.

source

pub const fn allow_shadowing(&self) -> bool

Is variables shadowing allowed? Default is true.

source

pub fn set_allow_shadowing(&mut self, enable: bool) -> &mut Engine

Set whether variables shadowing is allowed.

source

pub const fn strict_variables(&self) -> bool

Is strict variables mode enabled? Default is false.

source

pub fn set_strict_variables(&mut self, enable: bool) -> &mut Engine

Set whether strict variables mode is enabled.

source

pub const fn fail_on_invalid_map_property(&self) -> bool

Raise error if an object map property does not exist? Default is false.

Not available under no_object.

source

pub fn set_fail_on_invalid_map_property(&mut self, enable: bool) -> &mut Engine

Set whether to raise error if an object map property does not exist.

Not available under no_object.

source

pub const fn fast_operators(&self) -> bool

Is fast operators mode enabled? Default is false.

source

pub fn set_fast_operators(&mut self, enable: bool) -> &mut Engine

Set whether fast operators mode is enabled.

source§

impl Engine

source

pub fn on_var( &mut self, callback: impl Fn(&str, usize, EvalContext<'_, '_, '_, '_, '_, '_>) -> Result<Option<Dynamic>, Box<EvalAltResult>> + SendSync + 'static ) -> &mut Engine

👎Deprecated: This API is NOT deprecated, but it is considered volatile and may change in the future.

Provide a callback that will be invoked before each variable access.

§WARNING - Unstable API

This API is volatile and may change in the future.

§Callback Function Signature

Fn(name: &str, index: usize, context: EvalContext) -> Result<Option<Dynamic>, Box<EvalAltResult>>

where:

  • name: name of the variable.
  • index: an offset from the bottom of the current Scope that the variable is supposed to reside. Offsets start from 1, with 1 meaning the last variable in the current Scope. Essentially the correct variable is at position scope.len() - index. If index is zero, then there is no pre-calculated offset position and a search through the current Scope must be performed.
  • context: the current evaluation context.
§Return value
  • Ok(None): continue with normal variable access.
  • Ok(Some(Dynamic)): the variable’s value.
§Raising errors

Return Err(...) if there is an error.

§Example
use rhai::Engine;

let mut engine = Engine::new();

// Register a variable resolver.
engine.on_var(|name, _, _| {
    match name {
        "MYSTIC_NUMBER" => Ok(Some(42_i64.into())),
        _ => Ok(None)
    }
});

engine.eval::<i64>("MYSTIC_NUMBER")?;
source

pub fn on_def_var( &mut self, callback: impl Fn(bool, VarDefInfo<'_>, EvalContext<'_, '_, '_, '_, '_, '_>) -> Result<bool, Box<EvalAltResult>> + SendSync + 'static ) -> &mut Engine

👎Deprecated: This API is NOT deprecated, but it is considered volatile and may change in the future.

Provide a callback that will be invoked before the definition of each variable .

§WARNING - Unstable API

This API is volatile and may change in the future.

§Callback Function Signature

Fn(is_runtime: bool, info: VarInfo, context: EvalContext) -> Result<bool, Box<EvalAltResult>>

where:

  • is_runtime: true if the variable definition event happens during runtime, false if during compilation.
  • info: information on the variable.
  • context: the current evaluation context.
§Return value
  • Ok(true): continue with normal variable definition.
  • Ok(false): deny the variable definition with an runtime error.
§Raising errors

Return Err(...) if there is an error.

§Example
use rhai::Engine;

let mut engine = Engine::new();

// Register a variable definition filter.
engine.on_def_var(|_, info, _| {
    // Disallow defining MYSTIC_NUMBER as a constant
    if info.name() == "MYSTIC_NUMBER" && info.is_const() {
        Ok(false)
    } else {
        Ok(true)
    }
});

// The following runs fine:
engine.eval::<i64>("let MYSTIC_NUMBER = 42;")?;

// The following will cause an error:
engine.eval::<i64>("const MYSTIC_NUMBER = 42;")?;
source

pub fn on_print( &mut self, callback: impl Fn(&str) + SendSync + 'static ) -> &mut Engine

Override default action of print (print to stdout using println!)

§Example
use rhai::Engine;

let result = Arc::new(RwLock::new(String::new()));

let mut engine = Engine::new();

// Override action of 'print' function
let logger = result.clone();
engine.on_print(move |s| logger.write().unwrap().push_str(s));

engine.run("print(40 + 2);")?;

assert_eq!(*result.read().unwrap(), "42");
source

pub fn on_debug( &mut self, callback: impl Fn(&str, Option<&str>, Position) + SendSync + 'static ) -> &mut Engine

Override default action of debug (print to stdout using println!)

§Callback Function Signature

The callback function signature passed takes the following form:

Fn(text: &str, source: Option<&str>, pos: Position)

where:

  • text: the text to display
  • source: current source, if any
  • pos: location of the debug call
§Example
use rhai::Engine;

let result = Arc::new(RwLock::new(String::new()));

let mut engine = Engine::new();

// Override action of 'print' function
let logger = result.clone();
engine.on_debug(move |s, src, pos| logger.write().unwrap().push_str(
                    &format!("{} @ {:?} > {}", src.unwrap_or("unknown"), pos, s)
               ));

let mut ast = engine.compile(r#"let x = "hello"; debug(x);"#)?;
ast.set_source("world");
engine.run_ast(&ast)?;

#[cfg(not(feature = "no_position"))]
assert_eq!(*result.read().unwrap(), r#"world @ 1:18 > "hello""#);
#[cfg(feature = "no_position")]
assert_eq!(*result.read().unwrap(), r#"world @ none > "hello""#);
source§

impl Engine

source

pub fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str

Pretty-print a type name.

If a type is registered via register_type_with_name, the type name provided for the registration will be used.

source

pub fn compact_script( &self, script: impl AsRef<str> ) -> Result<String, ParseError>

Compact a script to eliminate insignificant whitespaces and comments.

This is useful to prepare a script for further compressing.

The output script is semantically identical to the input script, except smaller in size.

Unlike other uglifiers and minifiers, this method does not rename variables nor perform any optimization on the input script.

source§

impl Engine

source

pub fn register_custom_syntax<S>( &mut self, symbols: impl AsRef<[S]>, scope_may_be_changed: bool, func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_>, &[Expression<'_>]) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static ) -> Result<&mut Engine, ParseError>
where S: AsRef<str> + Into<SmartString<LazyCompact>>,

Register a custom syntax with the Engine.

Not available under no_custom_syntax.

  • symbols holds a slice of strings that define the custom syntax.
  • scope_may_be_changed specifies variables may be added/removed by this custom syntax.
  • func is the implementation function.
§Note on symbols
  • Whitespaces around symbols are stripped.
  • Symbols that are all-whitespace or empty are ignored.
  • If symbols does not contain at least one valid token, then the custom syntax registration is simply ignored.
§Note on scope_may_be_changed

If scope_may_be_changed is true, then size of the current Scope may be modified by this custom syntax.

Adding new variables and/or removing variables count.

Simply modifying the values of existing variables does NOT count, as the size of the current Scope is unchanged, so false should be passed.

Replacing one variable with another (i.e. adding a new variable and removing one variable at the same time so that the total size of the Scope is unchanged) also does NOT count, so false should be passed.

source

pub fn register_custom_syntax_with_state_raw( &mut self, key: impl Into<SmartString<LazyCompact>>, parse: impl Fn(&[ImmutableString], &str, &mut Dynamic) -> Result<Option<ImmutableString>, ParseError> + SendSync + 'static, scope_may_be_changed: bool, func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_>, &[Expression<'_>], &Dynamic) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static ) -> &mut Engine

Register a custom syntax with the Engine with custom user-defined state.

Not available under no_custom_syntax.

§WARNING - Low Level API

This function is very low level.

  • scope_may_be_changed specifies variables have been added/removed by this custom syntax.
  • parse is the parsing function.
  • func is the implementation function.

All custom keywords used as symbols must be manually registered via Engine::register_custom_operator. Otherwise, they won’t be recognized.

§Parsing Function Signature

The parsing function has the following signature:

Fn(symbols: &[ImmutableString], look_ahead: &str, state: &mut Dynamic) -> Result<Option<ImmutableString>, ParseError>

where:

  • symbols: a slice of symbols that have been parsed so far, possibly containing $expr$ and/or $block$; $ident$ and other literal markers are replaced by the actual text
  • look_ahead: a string slice containing the next symbol that is about to be read
  • state: a Dynamic value that contains a user-defined state
§Return value
  • Ok(None): parsing complete and there are no more symbols to match.
  • Ok(Some(symbol)): the next symbol to match, which can also be $expr$, $ident$ or $block$.
  • Err(ParseError): error that is reflected back to the Engine, normally ParseError(ParseErrorType::BadInput(LexError::ImproperSymbol(message)), Position::NONE) to indicate a syntax error, but it can be any ParseError.
source§

impl Engine

source

pub fn build_type<T>(&mut self) -> &mut Engine
where T: CustomType,

Build the API of a custom type for use with the Engine.

The custom type must implement CustomType.

source§

impl Engine

source

pub fn consume_file(&self, path: PathBuf) -> Result<(), Box<EvalAltResult>>

👎Deprecated since 1.1.0: use run_file instead

Evaluate a file, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.

Not available under no_std or WASM.

§Deprecated

This method is deprecated. Use run_file instead.

This method will be removed in the next major version.

source

pub fn consume_file_with_scope( &self, scope: &mut Scope<'_>, path: PathBuf ) -> Result<(), Box<EvalAltResult>>

👎Deprecated since 1.1.0: use run_file_with_scope instead

Evaluate a file with own scope, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.

Not available under no_std or WASM.

§Deprecated

This method is deprecated. Use run_file_with_scope instead.

This method will be removed in the next major version.

source

pub fn consume(&self, script: &str) -> Result<(), Box<EvalAltResult>>

👎Deprecated since 1.1.0: use run instead

Evaluate a string, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.

§Deprecated

This method is deprecated. Use run instead.

This method will be removed in the next major version.

source

pub fn consume_with_scope( &self, scope: &mut Scope<'_>, script: &str ) -> Result<(), Box<EvalAltResult>>

👎Deprecated since 1.1.0: use run_with_scope instead

Evaluate a string with own scope, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.

§Deprecated

This method is deprecated. Use run_with_scope instead.

This method will be removed in the next major version.

source

pub fn consume_ast(&self, ast: &AST) -> Result<(), Box<EvalAltResult>>

👎Deprecated since 1.1.0: use run_ast instead

Evaluate an AST, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.

§Deprecated

This method is deprecated. Use run_ast instead.

This method will be removed in the next major version.

source

pub fn consume_ast_with_scope( &self, scope: &mut Scope<'_>, ast: &AST ) -> Result<(), Box<EvalAltResult>>

👎Deprecated since 1.1.0: use run_ast_with_scope instead

Evaluate an AST with own scope, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.

§Deprecated

This method is deprecated. Use run_ast_with_scope instead.

This method will be removed in the next major version.

source

pub fn register_result_fn<A, const N: usize, const X: bool, R>( &mut self, name: impl AsRef<str> + Into<SmartString<LazyCompact>>, func: impl RhaiNativeFunc<A, N, X, R, true> + SendSync + 'static ) -> &mut Engine
where A: 'static, R: Variant + Clone,

👎Deprecated since 1.9.1: use register_fn instead

Register a custom fallible function with the Engine.

§Deprecated

This method is deprecated. Use register_fn instead.

This method will be removed in the next major version.

source

pub fn register_get_result<T, const X: bool, R>( &mut self, name: impl AsRef<str>, get_fn: impl RhaiNativeFunc<(Mut<T>,), 1, X, R, true> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, R: Variant + Clone,

👎Deprecated since 1.9.1: use register_get instead

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 instead.

This method will be removed in the next major version.

source

pub fn register_set_result<T, V, const X: bool>( &mut self, name: impl AsRef<str>, set_fn: impl RhaiNativeFunc<(Mut<T>, V), 2, X, (), true> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, V: Variant + Clone,

👎Deprecated since 1.9.1: use register_set instead

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 instead.

This method will be removed in the next major version.

source

pub fn register_indexer_get_result<T, IDX, R, const X: bool>( &mut self, get_fn: impl RhaiNativeFunc<(Mut<T>, IDX), 2, X, R, true> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, IDX: Variant + Clone, R: Variant + Clone,

👎Deprecated since 1.9.1: use register_indexer_get instead

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 instead.

This method will be removed in the next major version.

source

pub fn register_indexer_set_result<T, IDX, R, const X: bool>( &mut self, set_fn: impl RhaiNativeFunc<(Mut<T>, IDX, R), 3, X, (), true> + SendSync + 'static ) -> &mut Engine
where T: Variant + Clone, IDX: Variant + Clone, R: Variant + Clone,

👎Deprecated since 1.9.1: use register_indexer_set instead

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 instead.

This method will be removed in the next major version.

source

pub fn register_custom_syntax_raw( &mut self, key: impl Into<SmartString<LazyCompact>>, parse: impl Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError> + SendSync + 'static, scope_may_be_changed: bool, func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_>, &[Expression<'_>]) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static ) -> &mut Engine

👎Deprecated since 1.11.0: use register_custom_syntax_with_state_raw instead

Register a custom syntax with the Engine.

Not available under no_custom_syntax.

§Deprecated

This method is deprecated. Use register_custom_syntax_with_state_raw instead.

This method will be removed in the next major version.

source§

impl Engine

source

pub fn disable_symbol( &mut self, symbol: impl Into<SmartString<LazyCompact>> ) -> &mut Engine

Disable a particular keyword or operator in the language.

§Examples

The following will raise an error during parsing because the if keyword is disabled and is recognized as a reserved symbol!

use rhai::Engine;

let mut engine = Engine::new();

engine.disable_symbol("if");    // disable the 'if' keyword

engine.compile("let x = if true { 42 } else { 0 };")?;
//                      ^ 'if' is rejected as a reserved symbol

The following will raise an error during parsing because the += operator is disabled.

use rhai::Engine;

let mut engine = Engine::new();

engine.disable_symbol("+=");    // disable the '+=' operator

engine.compile("let x = 42; x += 1;")?;
//                            ^ unknown operator
source

pub fn is_symbol_disabled(&self, symbol: &str) -> bool

Is a particular keyword or operator disabled?

§Examples
use rhai::Engine;

let mut engine = Engine::new();

engine.disable_symbol("if");    // disable the 'if' keyword

assert!(engine.is_symbol_disabled("if"));
source

pub fn register_custom_operator( &mut self, keyword: impl AsRef<str>, precedence: u8 ) -> Result<&mut Engine, String>

Register a custom operator with a precedence into the language.

Not available under no_custom_syntax.

The operator can be a valid identifier, a reserved symbol, a disabled operator or a disabled keyword.

The precedence cannot be zero.

§Example
use rhai::Engine;

let mut engine = Engine::new();

// Register a custom operator called '#' and give it
// a precedence of 160 (i.e. between +|- and *|/).
engine.register_custom_operator("#", 160).expect("should succeed");

// Register a binary function named '#'
engine.register_fn("#", |x: i64, y: i64| (x * y) - (x + y));

assert_eq!(
    engine.eval_expression::<i64>("1 + 2 * 3 # 4 - 5 / 6")?,
    15
);
source

pub const fn default_tag(&self) -> &Dynamic

Get the default value of the custom state for each evaluation run.

source

pub fn default_tag_mut(&mut self) -> &mut Dynamic

Get a mutable reference to the default value of the custom state for each evaluation run.

source

pub fn set_default_tag(&mut self, value: impl Into<Dynamic>) -> &mut Engine

Set the default value of the custom state for each evaluation run.

source§

impl Engine

source

pub const RAW: Engine = _

An empty raw Engine.

source

pub fn new() -> Engine

Create a new Engine.

source

pub const fn new_raw() -> Engine

Create a new Engine with minimal built-in functions. It returns a copy of Engine::RAW.

This is useful for creating a custom scripting engine with only the functions you need.

Use register_global_module to add packages of functions.

source

pub fn get_interned_string( &self, string: impl AsRef<str> + Into<ImmutableString> ) -> ImmutableString

Get an interned string.

Engine keeps a cache of ImmutableString instances and tries to avoid new allocations and save memory when an existing instance is found.

It is usually a good idea to intern strings if they are used frequently.

source

pub fn const_empty_string(&self) -> ImmutableString

Get an empty ImmutableString which refers to a shared instance.

Trait Implementations§

source§

impl Debug for Engine

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Default for Engine

source§

fn default() -> Engine

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Engine

§

impl Send for Engine

§

impl Sync for Engine

§

impl Unpin for Engine

§

impl !UnwindSafe for Engine

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.