177 lines
5.7 KiB
Rust
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!");
|
|
}
|