This repository has been archived on 2025-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
rhaj/rhai_wrapper/examples/rust_rhai_wrapper_example.rs
2025-05-13 02:00:35 +03:00

177 lines
5.7 KiB
Rust

use rhai::Engine;
use rhai_wrapper::rust_rhai_wrapper;
use std::error::Error;
use std::fmt;
// Define a custom error type for Result examples
#[derive(Debug, Clone)]
struct MyError(String);
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Error for MyError {}
impl From<String> for MyError {
fn from(s: String) -> Self {
MyError(s)
}
}
fn main() {
// Create a Rhai engine
let mut engine = Engine::new();
// 1. Basic example: Add two numbers
// Define the original Rust function
fn add(a: i32, b: i32) -> i32 {
a + b
}
// Register it with Rhai
engine.register_fn("add_rhai", add);
// Create a wrapper function that calls Rhai which calls the Rust function
rust_rhai_wrapper!(add_via_rhai, "add_rhai", (i32, i32) -> i32);
// Test the full circle
let result = add_via_rhai(&mut engine, 5, 3);
println!("add_via_rhai(5, 3) = {}", result);
// 2. String manipulation example
fn concat(s1: String, s2: String) -> String {
format!("{} {}", s1, s2)
}
engine.register_fn("concat_rhai", concat);
rust_rhai_wrapper!(concat_via_rhai, "concat_rhai", (String, String) -> String);
let result = concat_via_rhai(&mut engine, "Hello".to_string(), "World".to_string());
println!("concat_via_rhai(\"Hello\", \"World\") = {}", result);
// 3. Function with no arguments
fn get_random() -> i32 {
42 // Not so random, but it's just an example
}
engine.register_fn("get_random_rhai", get_random);
rust_rhai_wrapper!(get_random_via_rhai, "get_random_rhai", () -> i32);
let result = get_random_via_rhai(&mut engine);
println!("get_random_via_rhai() = {}", result);
// 4. Function with more arguments
fn calculate(a: i32, b: i32, c: i32, d: i32) -> i32 {
a + b * c - d
}
engine.register_fn("calculate_rhai", calculate);
rust_rhai_wrapper!(calculate_via_rhai, "calculate_rhai", (i32, i32, i32, i32) -> i32);
let result = calculate_via_rhai(&mut engine, 5, 3, 2, 1);
println!("calculate_via_rhai(5, 3, 2, 1) = {}", result);
// 5. Function that handles errors with a custom return type
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
// Register a safe division function that returns an array with success flag and result/error
engine.register_fn("safe_divide", |a: i32, b: i32| -> rhai::Array {
if b == 0 {
// Return [false, error message]
let mut arr = rhai::Array::new();
arr.push(rhai::Dynamic::from(false));
arr.push(rhai::Dynamic::from("Division by zero"));
arr
} else {
// Return [true, result]
let mut arr = rhai::Array::new();
arr.push(rhai::Dynamic::from(true));
arr.push(rhai::Dynamic::from(a / b));
arr
}
});
// Create a wrapper for the safe_divide function
rust_rhai_wrapper!(safe_divide_via_rhai, "safe_divide", (i32, i32) -> rhai::Array);
// Test success case
let result = safe_divide_via_rhai(&mut engine, 10, 2);
println!("safe_divide_via_rhai(10, 2) = {:?}", result);
// Test error case
let result = safe_divide_via_rhai(&mut engine, 10, 0);
println!("safe_divide_via_rhai(10, 0) = {:?}", result);
// Process the result
let success = result[0].as_bool().unwrap();
if success {
println!("Division result: {}", result[1].as_int().unwrap());
} else {
println!("Division error: {}", result[1].clone().into_string().unwrap());
}
// 6. Complex example: Using a custom type with Rhai
#[derive(Debug, Clone)]
struct Person {
name: String,
age: i32,
}
// Register type and methods with Rhai
engine.register_type::<Person>();
engine.register_fn("new_person", |name: String, age: i32| -> Person {
Person { name, age }
});
engine.register_fn("get_name", |p: &mut Person| -> String {
p.name.clone()
});
engine.register_fn("get_age", |p: &mut Person| -> i32 {
p.age
});
engine.register_fn("is_adult", |p: &mut Person| -> bool {
p.age >= 18
});
// Register a function that creates a person and checks if they're an adult
engine.register_fn("create_and_check_person", |name: String, age: i32| -> rhai::Array {
let person = Person { name, age };
let is_adult = person.age >= 18;
// Create an array with the person and the is_adult flag
let mut arr = rhai::Array::new();
// Convert the person to a map for Rhai
let mut map = rhai::Map::new();
map.insert("name".into(), rhai::Dynamic::from(person.name));
map.insert("age".into(), rhai::Dynamic::from(person.age));
arr.push(rhai::Dynamic::from(map));
arr.push(rhai::Dynamic::from(is_adult));
arr
});
// Create a wrapper for the Rhai function
rust_rhai_wrapper!(create_person_via_rhai, "create_and_check_person", (String, i32) -> rhai::Array);
// Test the wrapper
let result = create_person_via_rhai(&mut engine, "Alice".to_string(), 25);
println!("create_person_via_rhai(\"Alice\", 25) = {:?}", result);
// Extract data from the Rhai array
let person_map = result[0].clone().try_cast::<rhai::Map>().expect("Expected a Map");
let is_adult = result[1].clone().as_bool().expect("Expected a boolean");
println!("Person: {:?}, Is Adult: {}", person_map, is_adult);
println!("All examples completed successfully!");
}