### Install Rhai Tools with All Features Source: https://rhai.rs/book/start/bin.html Installs all Rhai binary tools with all available features enabled. This is the most comprehensive installation option. ```bash cargo install --path . --bins --features bin-features ``` -------------------------------- ### Create and Run a Basic Rhai Script Source: https://rhai.rs/book/engine/hello-world.html Instantiate the Rhai engine and execute a simple script that prints output to the console. This is the most basic way to get started with Rhai. ```rust use rhai::{Engine, EvalAltResult}; pub fn main() -> Result<(), Box> { // Create an 'Engine' let engine = Engine::new(); // Your first Rhai Script let script = "print(40 + 2);"; // Run the script - prints "42" engine.run(script)?; // Done! Ok(()) } ``` -------------------------------- ### Install Specific Rhai App with Features Source: https://rhai.rs/book/start/bin.html Installs a specific Rhai binary application, 'sample_app_to_run', with the 'bin-features' enabled. Use this for targeted installations. ```bash cargo install --path . --bin sample_app_to_run --features bin-features ``` -------------------------------- ### Install rhai-doc Source: https://rhai.rs/book/tools/rhai-doc.html Install the `rhai-doc` tool using cargo. ```bash cargo install rhai-doc ``` -------------------------------- ### Run Rhai Examples Source: https://rhai.rs/book/start/examples/rust.html Command to run specific Rhai examples. Replace {example_name} with the desired example directory name. ```bash cargo run --example {example_name} ``` -------------------------------- ### Example Usage of Custom Syntax Source: https://rhai.rs/book/engine/custom-syntax.html Demonstrates how to use a custom syntax in Rhai code. This example shows a custom 'exec' statement and how variables declared within it persist. ```rhai // Assuming the 'exec' custom syntax implementation declares the variable 'hello': let x = exec [hello < 42] <- foo(1, 2) : { hello += bar(hello); baz(hello); }; print(x); // variable 'x' has a value returned by the custom syntax print(hello); // variable declared by a custom syntax persists! ``` -------------------------------- ### Example Rhai Configuration Script Source: https://rhai.rs/book/patterns/config.html A sample Rhai script demonstrating how to call the registered configuration functions to set values, add to lists, and populate maps. ```rhai ┌────────────────┐ │ my_config.rhai │ └────────────────┘ config_set_id("hello"); config_add("foo"); // add to list config_add("bar", true); // add to map if config_contains("hey") || config_is_set("hey") { config_add("baz", false); // add to map } ``` -------------------------------- ### Basic Tag Manipulation in Rhai Source: https://rhai.rs/book/language/dynamic-tag.html Demonstrates how to set, get, and use tags with integer values. Shows default tag behavior, direct assignment, function calls, and bit-field operations. Includes an example of a runtime error for out-of-bounds tag values. ```rhai let x = 42; x.tag == 0; // tag defaults to zero x.tag = 123; // set tag value set_tag(x, 123); // 'set_tag' function also works x.tag == 123; // get updated tag value x.tag() == 123; // method also works tag(x) == 123; // function call style also works x.tag[3..5] = 2; // tag can be used as a bit-field x.tag[3..5] == 2; let y = x; y.tag == 123; // the tag is copied across assignment y.tag = 3000000000; // runtime error: 3000000000 is too large for 'i32' ``` -------------------------------- ### Run Rhai App with Features Source: https://rhai.rs/book/start/bin.html Executes a Rhai binary application, 'sample_app_to_run', using Cargo, ensuring that 'bin-features' are enabled. This is an alternative to direct installation. ```bash cargo run --features bin-features --bin sample_app_to_run ``` -------------------------------- ### Rhai Infinite Loop Examples Source: https://rhai.rs/book/safety/max-operations.html Illustrates syntax for creating infinite loops in Rhai, including a basic `loop` and a `while` loop with a perpetually true condition. ```rhai loop { ... } // infinite loop while 1 < 2 { ... } // loop with always-true condition ``` -------------------------------- ### Exporting and Registering a Basic Function Source: https://rhai.rs/book/plugins/function.html This example demonstrates how to export a Rust function using `#[export_fn]` and register it with the Rhai engine under a new name using `register_exported_fn!`. ```APIDOC ## `#[export_fn]` and `register_exported_fn!` Apply `#[export_fn]` onto a function defined at _Rust module level_ to convert it into a Rhai plugin function. To register the plugin function, simply call `register_exported_fn!`. ```rust use rhai::plugin::*; #[export_fn] fn increment(num: &mut i64) { *num += 1; } fn main() { let mut engine = Engine::new(); // 'register_exported_fn!' registers the function as 'inc' with the Engine. register_exported_fn!(engine, "inc", increment); } ``` ``` -------------------------------- ### Constant Propagation Example Source: https://rhai.rs/book/engine/optimize/constants.html Demonstrates how constants like booleans and numbers are replaced with their literal values, and how logical OR short-circuiting affects execution. ```rust const ABC = true; const X = 41; if ABC || calc(X+1) { print("done!"); } // 'ABC' is constant so replaced by 'true'... // 'X' is constant so replaced by 41... if true || calc(42) { print("done!"); } // '41+1' is replaced by 42 // since '||' short-circuits, 'calc' is never called if true { print("done!"); } // <- the line above is equivalent to this print("done!"); // <- the line above is further simplified to this // because the condition is always true ``` -------------------------------- ### Function Call Example for Hash Calculation Source: https://rhai.rs/book/rust/dynamic-args.html Demonstrates a typical function call used to illustrate the hash calculation process for matching overloaded functions with `Dynamic` parameters. ```rust foo(42, "hello", true); ``` -------------------------------- ### Simulate Command-Style Custom Syntax Source: https://rhai.rs/book/engine/custom-syntax-parsers.html Use this pattern for custom syntax where multiple commands share a common starting symbol. Each line represents a distinct command. ```rust // The following simulates a command-style syntax, all starting with 'perform'. perform hello world; // A fixed sequence of symbols perform action 42; // Perform a system action with a parameter perform update system; // Update the system perform check all; // Check all system settings perform cleanup; // Clean up the system perform add something; // Add something to the system perform remove something; // Delete something from the system ``` -------------------------------- ### Rhai Arithmetic and Bitwise Operators Source: https://rhai.rs/book/language/num-op.html Shows examples of common arithmetic and bitwise operations, including addition, subtraction, multiplication, division, modulo, exponentiation, and bit shifts. ```rhai let x = (1 + 2) * (6 - 4) / 2; // arithmetic, with parentheses let reminder = 42 % 10; // modulo let power = 42 ** 2; // power let left_shifted = 42 << 3; // left shift let right_shifted = 42 >> 3; // right shift let bit_op = 42 | 99; // bit masking ``` -------------------------------- ### Run Rhai REPL with Initialization Scripts Source: https://rhai.rs/book/start/bin.html Starts the Rhai REPL tool, first executing 'init1.rhai', 'init2.rhai', and 'init3.rhai' to load functions into the global namespace before entering the interactive session. ```bash rhai-repl init1.rhai init2.rhai init3.rhai ``` -------------------------------- ### Rhai Implementation Function with '$$' Return Symbol Source: https://rhai.rs/book/engine/custom-syntax-parsers.html An example implementation function that uses the '$$' prefix in return symbols to identify which custom syntax variant was parsed. This function expects symbols starting with '$$' to terminate parsing and add the symbol to the input stream. ```rust __ fn implementation_fn(context: &mut EvalContext, inputs: &[Expression], state: &Dynamic) -> Result> { // Get the last symbol let key = inputs.last().unwrap().get_string_value().unwrap(); // Make sure it starts with '$$' assert!(key.starts_with("$$")); // Execute the custom syntax expression match key { "$$hello" => { ... } "$$world" => { ... } "$$foo" => { ... } "$$bar" => { ... } _ => Err(...) } } ``` -------------------------------- ### Rhai Engine Setup with `|>` Closure Source: https://rhai.rs/book/rust/packages/create.html Demonstrates the use of the `|>` syntax to provide a closure for setting up an Engine instance when a package is registered. This allows for direct manipulation of the Engine, such as registering custom types or operators. ```rust def_package! { pub MyPackage(module) { : : } |> |engine| { // Call methods on 'engine' } } ``` -------------------------------- ### Basic Import and Module Usage Source: https://rhai.rs/book/ref/modules/import.html Demonstrates running a script directly, importing a script with an alias, and dynamically constructing module paths. Access module members using the `::` operator. ```rhai import "crypto_banner"; // run the script file 'crypto_banner.rhai' without creating an imported module import "crypto" as lock; // run the script file 'crypto.rhai' and import it as a module named 'lock' const SECRET_NUMBER = 42; let mod_file = `crypto_${SECRET_NUMBER}`; import mod_file as my_mod; // load the script file "crypto_42.rhai" and import it as a module named 'my_mod' // notice that module path names can be dynamically constructed! // any expression that evaluates to a string is acceptable after the 'import' keyword lock::encrypt(secret); // use functions defined under the module via '::' lock::hash::sha256(key); // sub-modules are also supported print(lock::status); // module variables are constants lock::status = "off"; // <- runtime error: cannot modify a constant ``` -------------------------------- ### Extracting Substrings with Range Indexing (Exclusive) Source: https://rhai.rs/book/ref/strings-chars.html Substrings can be extracted using a range index `[start..end]`, where `start` is the inclusive starting character index and `end` is the exclusive ending character index. Negative ranges are not supported. ```rhai // Example: Get characters from index 2 up to (but not including) index 5 let sub = s[2..5]; ``` -------------------------------- ### EnergizerBunny API Example Source: https://rhai.rs/book/patterns/control.html This Rust code defines a simple EnergizerBunny struct with methods to control its state and speed. It serves as an example of a system that can be controlled by Rhai scripts. ```rust struct EnergizerBunny; impl EnergizerBunny { pub fn new () -> Self { ... } pub fn go (&mut self) { ... } pub fn stop (&mut self) { ... } pub fn is_going (&self) { ... } pub fn get_speed (&self) -> i64 { ... } pub fn set_speed (&mut self, speed: i64) { ... } } ``` -------------------------------- ### Macro Expansion Example in Rust Source: https://rhai.rs/book/patterns/macros.html Demonstrates how to use Rust's string replace method to expand macro-like syntax in a script before execution. This is useful for simplifying complex property access chains. ```rust let script = script.replace("#FOO", "foo[x][y].bar[z].baz"); let mut scope = Scope::new(); // Add global variables scope.push("foo", ...); scope.push_constant("x", ...); scope.push_constant("y", ...); scope.push_constant("z", ...); // Run the script as normal engine.run_with_scope(&mut scope, script)?; ``` -------------------------------- ### Getting Dynamic Value Type Name Source: https://rhai.rs/book/language/dynamic-rust.html Use `type_name` to get the full Rust path name of the data within a Dynamic value, useful for pattern matching. ```rust let list: Array = engine.eval("...")?; let item = list[0]; match item.type_name() { "()" => ... "i64" => ... "f64" => ... "rust_decimal::Decimal" => ... "core::ops::range::Range" => ... "core::ops::range::RangeInclusive" => ... "alloc::string::String" => ... "bool" => ... "char" => ... "rhai::FnPtr" => ... "std::time::Instant" => ... "crate::path::to::module::TestStruct" => ... : } ``` -------------------------------- ### Configure `no-std` Build with Allocator and Panic Handlers Source: https://rhai.rs/book/start/builds/no-std.html This example demonstrates the necessary Rust compiler flags, external crate inclusions, and handler implementations for a `no-std` environment. It includes setting up `wee_alloc` as the global allocator and defining custom panic and error handlers that abort the program. ```rust #![no_std] #![feature(alloc_error_handler, start, core_intrinsics, lang_items, link_cfg)] extern crate alloc; extern crate wee_alloc; #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[cfg(all(windows, target_env = "msvc"))] #[link(name = "msvcrt")] #[link(name = "libcmt")] extern "C" {} #[alloc_error_handler] fn err_handler(_: core::alloc::Layout) -> ! { core::intrinsics::abort(); } #[panic_handler] #[lang = "panic_impl"] extern "C" fn rust_begin_panic(_: &core::panic::PanicInfo) -> ! { core::intrinsics::abort(); } #[lang = "eh_personality"] extern "C" fn eh_personality() {} #[no_mangle] extern "C" fn rust_eh_register_frames() {} #[no_mangle] extern "C" fn rust_eh_unregister_frames() {} #[no_mangle] extern "C" fn _Unwind_Resume() {} #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { // ... main program ... } ``` -------------------------------- ### Example of Deeply Nested Expression Source: https://rhai.rs/book/safety/max-stmt-depth.html This example demonstrates a deeply nested expression that could potentially cause a stack overflow during parsing if the maximum expression depth limits are exceeded. ```rust let a = (1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(...)+1))))))))))); ``` -------------------------------- ### Array Initialization and Basic Operations Source: https://rhai.rs/book/language/arrays.html Demonstrates array creation, insertion at specific indices, checking length, and accessing elements. Supports trailing commas in initialization. ```rhai let y = [2, 3]; // y == [2, 3] let y = [2, 3,]; // y == [2, 3] y.insert(0, 1); // y == [1, 2, 3] y.insert(999, 4); // y == [1, 2, 3, 4] y.len == 4; y[0] == 1; y[1] == 2; y[2] == 3; y[3] == 4; ``` -------------------------------- ### Create Function Pointer (Short-hand vs Fn) Source: https://rhai.rs/book/language/fn-ptr.html Demonstrates the short-hand notation for creating function pointers to script-defined functions, which is equivalent to using the `Fn` function. ```rhai fn foo() { ... } // function definition let f = foo; // function pointer to 'foo' let f = Fn("foo"); // <- the above is equivalent to this let g = bar; // error: variable 'bar' not found ``` -------------------------------- ### Function Signature for `get` Attribute Source: https://rhai.rs/book/rust/derive-custom-type.html When using the `get` attribute with `rhai_type`, the associated function must accept an immutable reference to the type (`&T`) and return the field's value (`V`). ```rust Fn(&T) -> V ``` -------------------------------- ### rhai-doc Configuration File Example Source: https://rhai.rs/book/tools/rhai-doc.html A sample `rhai.toml` configuration file for `rhai-doc`. This file customizes project name, theme color, root URL, index file, icon, stylesheet, code highlighting, script extension, and external links. ```toml name = "My Rhai Project" # project name color = [246, 119, 2] # theme color root = "/docs/" # root URL for generated site index = "home.md" # this file becomes 'index.html' icon = "logo.svg" # project icon stylesheet = "my_stylesheet.css" # custom stylesheet code_theme = "atom-one-light" # 'highlight.js' theme code_lang = "ts" # default language for code blocks extension = "rhai" # script extension google_analytics = "G-ABCDEF1234" # Google Analytics ID [[links]] # external link for 'Blog' name = "Blog" link = "https://example.com/blog" [[links]] # external link for 'Tools' name = "Tools" link = "https://example.com/tools" ``` -------------------------------- ### Extracting Substrings with Range Indexing (Inclusive) Source: https://rhai.rs/book/ref/strings-chars.html Substrings can also be extracted using an inclusive range index `[start..=end]`, where both `start` and `end` are inclusive character indices. Negative ranges are not supported. ```rhai // Example: Get characters from index 2 up to and including index 5 let sub = s[2..=5]; ``` -------------------------------- ### Using 'take' to Return Large Values from Functions Source: https://rhai.rs/book/language/assignment.html Demonstrates how to use 'take' to efficiently return large data structures from functions without cloning, contrasting it with a naive cloning approach. ```rhai fn get_large_value_naive() { let large_result = do_complex_calculation(); large_result.done = true; // Return a cloned copy of the result, then the // local variable 'large_result' is thrown away! large_result } fn get_large_value_smart() { let large_result = do_complex_calculation(); large_result.done = true; // Return the result without cloning! // Method style call is also OK. large_result.take() } ``` -------------------------------- ### Literal Strings with Leading Newline Stripped Source: https://rhai.rs/book/language/string-interp.html If a backtick (`) appears at the end of a line, the entire text block starts from the next line, and the starting new-line character is stripped. This is useful for formatting multi-line strings. ```rhai let x = " hello, world! \"\\t\\x42\" hello world again! 'x' this is the last time!!! "; ``` -------------------------------- ### Rhai Array Size Limit Example Source: https://rhai.rs/book/safety/max-array-size.html Demonstrates how Rhai detects and raises an error when an array tree exceeds the maximum size limit, even if individual arrays are small. This includes examples of recursive array growth and infinite loops creating nested arrays. ```rhai // Small, innocent array... let small_array = [42]; // 1-deep... 1 item, 1 array // ... becomes huge when multiplied! small_array.push(small_array); // 2-deep... 2 items, 2 arrays small_array.push(small_array); // 3-deep... 4 items, 4 arrays small_array.push(small_array); // 4-deep... 8 items, 8 arrays small_array.push(small_array); // 5-deep... 16 items, 16 arrays : : small_array.push(small_array); // <- Rhai raises an error somewhere here small_array.push(small_array); // when the TOTAL number of items in small_array.push(small_array); // the entire array tree exceeds limit // Or this abomination... let a = [ 42 ]; loop { a[0] = a; // <- only 1 item, but infinite number of arrays ``` -------------------------------- ### Example Script Using Custom SQL Syntax Source: https://rhai.rs/book/engine/custom-syntax-arbitrary-text.html This script demonstrates how to use the custom 'SELECT' syntax registered previously. It shows variable substitution for 'nobody', 'min_amount', and 'max_total', and block substitution for SQL clauses. ```rhai __ let nobody = "John Doe"; let min_amount = 100.0; let max_total = 1000.0; let records = SELECT id, SUM(amount) AS `total`, FIRST('http://hitme.com/') + id AS `link` FROM db.public.users WHERE name <> {nobody} AND amount >= {min_amount} GROUP BY id HAVING SUM(amount) <= @max_total; ``` -------------------------------- ### Get Character at Position Source: https://rhai.rs/book/ref/string-fn.html Retrieve a character from a string at a specific position. ```APIDOC ## get ### Description Gets the character at a certain position (returns `()` if the position is not valid). Position counts from the end if negative. ### Parameters #### Path Parameters - **position** (integer) - Description: Position to get the character from. Counting from the end if negative. ### Method Function ``` -------------------------------- ### Create and Configure Raw Engine Source: https://rhai.rs/book/engine/raw.html Creates a raw scripting engine, sets up a file-based module resolver, enables the strings interner, configures default print/debug handlers, and registers the Standard Package. Use this when you need a customized engine with specific functionalities. ```rust use rhai::module_resolvers::FileModuleResolver; use rhai::packages::StandardPackage; use rhai::Position; // Create a raw scripting Engine let mut engine = Engine::new_raw(); // Use the file-based module resolver engine.set_module_resolver(FileModuleResolver::new()); // Enable the strings interner engine.set_max_strings_interned(1024); // Default print/debug implementations engine.on_print(|text| println!("{text}")); engine.on_debug(|text, source, pos| match (source, pos) { (Some(source), Position::NONE) => println!("{source} | {text}"), (Some(source), pos) => println!("{source} @ {pos:?} | {text}"), (None, Position::NONE) => println!("{text}"), (None, pos) => println!("{pos:?}"), }); // Register the Standard Package let package = StandardPackage::new(); // Load the package into the [`Engine`] package.register_into_engine(&mut engine); ``` -------------------------------- ### String Length and Byte Count Source: https://rhai.rs/book/ref/string-fn.html Get the number of characters or bytes in a string. ```APIDOC ## len ### Description Returns the number of characters (not number of bytes) in the string. ### Method Property ## bytes ### Description Returns the number of bytes making up the UTF-8 string. For strings containing only ASCII characters, this is much faster than `len`. ### Method Property ``` -------------------------------- ### Create and Access Object Maps Source: https://rhai.rs/book/language/object-maps.html Demonstrates object map literal creation, property access using dot and index notation, and testing for property existence with the 'in' operator. Note syntax errors for invalid property names in dot notation. ```rhai let y = #{ // object map literal with 3 properties a: 1, bar: "hello", "baz!$@": 123.456, // like JavaScript, you can use any string as property names... "": false, // even the empty string! `hello`: 999, // literal strings are also OK a: 42, // <- syntax error: duplicated property name `a${2}`: 42, // <- syntax error: property name cannot have string interpolation }; y.a = 42; // access via dot notation y.a == 42; y.baz!$@ = 42; // <- syntax error: only proper variable names allowed in dot notation y."baz!$@" = 42; // <- syntax error: strings not allowed in dot notation y["baz!$@"] = 42; // access via index notation is OK "baz!$@" in y == true; // use 'in' to test if a property exists in the object map ("z" in y) == false; ts.obj = y; // object maps can be assigned completely (by value copy) let foo = ts.list.a; foo == 42; let foo = #{ a:1, }; // trailing comma is OK let foo = #{ a:1, b:2, c:3 }["a"]; let foo = #{ a:1, b:2, c:3 }.a; foo == 1; fn abc() { #{ a:1, b:2, c:3 } // a function returning an object map } let foo = abc().b; foo == 2; let foo = y["a"]; foo == 42; ``` -------------------------------- ### Crop String Source: https://rhai.rs/book/ref/string-fn.html Retain only a portion of a string based on start position and length, or a range. ```APIDOC ## crop ### Description Retains only a portion of the string. Can be used with a start position and a count, or with a range. ### Parameters #### Path Parameters - **start_position** (integer) - Description: The starting position for the portion to retain. Counting from the end if negative. - **count** (integer) - Optional. The number of characters to retain. None if ≤ 0, to the end if omitted. ### Method Function ## crop (range) ### Description Retains only a portion of the string using a range. ### Parameters #### Path Parameters - **range** (range) - Description: The range of characters to retain, from beginning if ≤ 0, to end if ≥ length. ### Method Function ``` -------------------------------- ### Extract Sub-string Source: https://rhai.rs/book/ref/string-fn.html Extract a portion of a string based on start position and length, or a range. ```APIDOC ## sub_string ### Description Extracts a sub-string. Can be used with a start position and a count, or with a range. ### Parameters #### Path Parameters - **start_position** (integer) - Description: The starting position for the sub-string. Counting from the end if negative. - **count** (integer) - Optional. The number of characters to extract. None if ≤ 0, to the end if omitted. ### Method Function ## sub_string (range) ### Description Extracts a sub-string using a range. ### Parameters #### Path Parameters - **range** (range) - Description: The range of characters to extract, from beginning if ≤ 0, to end if ≥ length. ### Method Function ``` -------------------------------- ### Rust vs. Rhai Builder API Usage Source: https://rhai.rs/book/patterns/builder.html Compares the fluent API usage of the builder pattern in Rust and Rhai scripts. Both examples demonstrate creating a `Foo` instance with various options. ```rust let mut engine = Engine::new(); engine.register_static_module("Foo", exported_module!(foo_builder).into()); let foo = FooBuilder::new().with_foo(42).with_bar(true).with_baz("Hello").build(); ``` ```rhai let foo = Foo::default().with_foo(42).with_bar(true).with_baz("Hello").create(); ``` -------------------------------- ### Create and Access Object Maps Source: https://rhai.rs/book/ref/object-maps.html Demonstrates object map literal syntax, property access via dot notation and index notation, and handling of non-existent properties. ```rhai let y = #{ // object map literal with 3 properties a: 1, bar: "hello", "baz!$@": 123.456, // like JavaScript, you can use any string as property names... "": false, // even the empty string! `hello`: 999, // literal strings are also OK a: 42, // <- syntax error: duplicated property name `a${2}`: 42, // <- syntax error: property name cannot have string interpolation }; y.a = 42; // access via dot notation y.a == 42; y.baz!$@ = 42; // <- syntax error: only proper variable names allowed in dot notation y."baz!$@" = 42; // <- syntax error: strings not allowed in dot notation y["baz!$@"] = 42; // access via index notation is OK "baz!$@" in y == true; // use 'in' to test if a property exists in the object map ("z" in y) == false; ts.obj = y; // object maps can be assigned completely (by value copy) let foo = ts.list.a; foo == 42; let foo = #{ a:1, }; // trailing comma is OK let foo = #{ a:1, b:2, c:3 }["a"]; let foo = #{ a:1, b:2, c:3 }.a; foo == 1; fn abc() { #{ a:1, b:2, c:3 } // a function returning an object map } let foo = abc().b; foo == 2; let foo = y["a"]; foo == 42; y.contains("a") == true; y.contains("xyz") == false; y.xyz == (); // a non-existent property returns '()' y["xyz"] == (); y.len == (); // an object map has no property getter function y.len() == 3; // method calls are OK y.remove("a") == 1; // remove property y.len() == 2; y.contains("a") == false; ``` -------------------------------- ### BLOB Accessor Functions Source: https://rhai.rs/book/language/blobs.html Functions to get or set individual bytes within a BLOB. ```APIDOC ## get ### Description Gets a copy of the byte at a certain position (0 if the position is not valid). Position can be counted from the end if negative. ### Parameters - position (integer) - The index of the byte to retrieve. Negative values count from the end. ``` ```APIDOC ## set ### Description Sets a certain position to a new value (no effect if the position is not valid). Position can be counted from the end if negative. ### Parameters 1. position (integer) - The index of the byte to set. Negative values count from the end. 2. new_byte (integer) - The new byte value to set. ``` -------------------------------- ### Infinite Recursion Example Source: https://rhai.rs/book/safety/max-call-stack.html This is a function that, when called, recurses forever, demonstrating a potential stack overflow. ```rust fn recurse_forever() { recurse_forever(); } ``` -------------------------------- ### Import and Use Configuration from Rhai Script Source: https://rhai.rs/book/patterns/config.html Shows how to import a Rhai script directly (without creating a module) and then use the exposed configuration functions to retrieve and check values. ```rhai import "my_config"; // run configuration script without creating a module let id = config_get_id(); id == "hello"; ``` -------------------------------- ### Register CorePackage into Multiple Engines Source: https://rhai.rs/book/rust/packages/index.html Demonstrates how to create a single package instance and register it into multiple raw Engine instances. This is efficient when spawning many engines. ```rust use rhai::Engine; use rhai::packages::Package // load the 'Package' trait to use packages use rhai::packages::CorePackage; // the 'core' package contains basic functionalities (e.g. arithmetic) // Create a package - can be shared among multiple 'Engine' instances let package = CorePackage::new(); let mut engines_collection: Vec = Vec::new(); // Create 100 'raw' Engines for _ in 0..100 { let mut engine = Engine::new_raw(); // Register the package into the global namespace. package.register_into_engine(&mut engine); engines_collection.push(engine); } ``` -------------------------------- ### BLOB Access and Modification Source: https://rhai.rs/book/ref/blobs.html Functions for getting, setting, inserting, and removing bytes within a BLOB. ```APIDOC ## BLOB Access and Modification ### Description Methods for accessing and modifying individual bytes or ranges within a BLOB. ### Methods - `get(position)`: Gets a copy of the byte at the specified position. Negative positions count from the end. Returns 0 if the position is invalid. - `set(position, new_byte_value)`: Sets the byte at the specified position to a new value. Negative positions count from the end. No effect if the position is invalid. - `insert(position, byte_to_insert)`: Inserts a byte at the specified position. Negative positions count from the end. If `position` is greater than or equal to the length, it's appended. - `remove(position)`: Removes the byte at the specified position and returns it. Negative positions count from the end. Returns 0 if the position is invalid. - `pop()`: Removes and returns the last byte of the BLOB. Returns 0 if the BLOB is empty. - `shift()`: Removes and returns the first byte of the BLOB. Returns 0 if the BLOB is empty. ``` -------------------------------- ### Using Print and Debug in Rhai Source: https://rhai.rs/book/ref/print-debug.html Demonstrates basic usage of `print` for strings, arithmetic expressions, and template literals, as well as `debug` for formatted output. ```rhai print("hello"); // prints "hello" to stdout print(1 + 2 + 3); // prints "6" to stdout let x = 42; print(`hello${x}`); // prints "hello42" to stdout debug("world!"); // prints "world!" to stdout using debug formatting ``` -------------------------------- ### Array Length and Emptiness Source: https://rhai.rs/book/language/arrays.html Methods and properties to get the size of an array and check if it's empty. ```APIDOC ## len method and property ### Description Returns the number of elements in the array. ### Method/Property `len()` or `array.len` ## is_empty method and property ### Description Returns `true` if the array is empty, `false` otherwise. ### Method/Property `is_empty()` or `array.is_empty` ``` -------------------------------- ### Initialize Event Handler with Custom Scope and API Source: https://rhai.rs/book/patterns/events.html Demonstrates the initialization of an event handler, including registering custom types and APIs, setting up a custom scope with constants and initial state, and compiling the script. ```rust impl Handler { // Create a new 'Handler'. pub fn new(path: impl Into) -> Self { let mut engine = Engine::new(); // Register custom types and APIs engine.register_type_with_name::("TestStruct") .register_global_module(exported_module!(test_struct_api).into()); // Create a custom 'Scope' to hold state let mut scope = Scope::new(); // Add any system-provided state into the custom 'Scope'. // Constants can be used to optimize the script. scope.push_constant("MY_CONSTANT", 42_i64); : : // Initialize state variables : : // Compile the handler script. // In a real application you'd be handling errors... let ast = engine.compile_file_with_scope(&mut scope, path).unwrap(); // The event handler is essentially these three items: Self { engine, scope, ast } } } ``` -------------------------------- ### Array Element Access and Modification Source: https://rhai.rs/book/language/arrays.html Methods for getting and setting elements within an array by their position. ```APIDOC ## get ### Description Gets a copy of the element at a certain position. Returns `()` if the position is not valid. ### Method `get(position)` ### Parameters * **position** (integer) - The index of the element to retrieve. Negative values count from the end. ## set ### Description Sets an element at a certain position to a new value. Has no effect if the position is not valid. ### Method `set(position, new_element)` ### Parameters * **position** (integer) - The index of the element to set. Negative values count from the end. * **new_element** (any) - The new value to assign to the element. ``` -------------------------------- ### Generate Definition Files with Options Source: https://rhai.rs/book/engine/metadata/definitions.html Configure definition file generation by chaining options like `with_headers` and `include_standard_packages`. Use `write_to_dir` to output the files. ```rust engine .definitions() .with_headers(true) // write headers in all files .include_standard_packages(false) // skip standard packages .write_to_dir("path/to/my/definitions") .unwrap(); ``` -------------------------------- ### BLOB Constructor Source: https://rhai.rs/book/language/blobs.html Creates a new BLOB. It can be initialized with a specific length and/or a starting byte value. ```APIDOC ## blob constructor function ### Description Creates a new BLOB, optionally of a particular length filled with an initial byte value (default = 0). ### Parameters 1. _(optional)_ initial length of the BLOB 2. _(optional)_ initial byte value ``` -------------------------------- ### Generate Documentation in `build.rs` Source: https://rhai.rs/book/lib/rhai-autodocs.html Use `rhai-autodocs` within your `build.rs` script to generate documentation. Ensure the `DOCS_DIR` environment variable is set to specify the output directory. ```rust fn main() { // Specify an environment variable that points to the directory // where the documentation will be generated. if let Ok(docs_path) = std::env::var("DOCS_DIR") { let mut engine = rhai::Engine::new(); // register custom functions and types... // or load packages... let docs = rhai_autodocs::options() .include_standard_packages(false) .generate(&engine) .expect("failed to generate documentation"); // Write the documentation to a file etc. } } ``` -------------------------------- ### Volatile Function Example Source: https://rhai.rs/book/engine/optimize/volatility.html Demonstrates how a volatile function call with constant arguments can be replaced by its result during full optimization. ```rust print(get_current_time(true)); // prints the current time // notice the call to 'get_current_time' // has constant arguments // The above, under full optimization level, is rewritten to: print("10:25AM"); // the function call is replaced by // its result at the time of optimization! ``` -------------------------------- ### Load FilesystemPackage into Rhai Engine Source: https://rhai.rs/book/lib/rhai-fs.html Instantiate the `FilesystemPackage` and register it with the Rhai `Engine` to enable filesystem operations within scripts. ```rust use rhai::Engine; use rhai::packages::Package; // needed for 'Package' trait use rhai_fs::FilesystemPackage; let mut engine = Engine::new(); // Create new 'FilesystemPackage' instance let fs = FilesystemPackage::new(); // Load the package into the `Engine` fs.register_into_engine(&mut engine); ``` -------------------------------- ### BLOB Reversal and Size Source: https://rhai.rs/book/ref/blobs.html Functions to reverse the byte order of a BLOB and to get its length or check if it's empty. ```APIDOC ## BLOB Reversal and Size ### Description Operations for reversing the byte order of a BLOB and querying its size properties. ### Methods/Properties - `reverse()`: Reverses the order of bytes within the BLOB. - `len()` or `len` property: Returns the number of bytes in the BLOB. - `is_empty()` or `is_empty` property: Returns `true` if the BLOB contains no bytes, `false` otherwise. ```