add engine and rpc client, archive old code

This commit is contained in:
timurgordon
2025-06-03 21:47:36 +03:00
parent 061aee6f1d
commit b20140785e
42 changed files with 10310 additions and 0 deletions

282
_archive/rhai_autobind_macros/Cargo.lock generated Normal file
View File

@@ -0,0 +1,282 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "ahash"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b"
dependencies = [
"cfg-if",
"const-random",
"getrandom",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "const-random"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
dependencies = [
"const-random-macro",
]
[[package]]
name = "const-random-macro"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
"getrandom",
"once_cell",
"tiny-keccak",
]
[[package]]
name = "crunchy"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
]
[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
dependencies = [
"portable-atomic",
]
[[package]]
name = "portable-atomic"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rhai"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1acc213aa1e33611a4b20b31b738af675113e1c9944d6e3d79e3e7318ce0205"
dependencies = [
"ahash",
"bitflags",
"instant",
"num-traits",
"once_cell",
"rhai_codegen",
"smallvec",
"smartstring",
"thin-vec",
]
[[package]]
name = "rhai_autobind_macros"
version = "0.1.0"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rhai",
"serde",
"syn",
]
[[package]]
name = "rhai_codegen"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "smallvec"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
[[package]]
name = "smartstring"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
dependencies = [
"autocfg",
"static_assertions",
"version_check",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thin-vec"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
[[package]]
name = "tiny-keccak"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -0,0 +1,17 @@
[package]
name = "rhai_autobind_macros"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
syn = { version = "2.0", features = ["full", "extra-traits"] }
quote = "1.0"
proc-macro2 = "1.0"
heck = "0.4"
[dev-dependencies]
rhai = "1.18.0"
serde = { version = "1.0", features = ["derive"] }

View File

@@ -0,0 +1,33 @@
// calculator.rhai
// This script demonstrates using the Calculator struct from Rust in Rhai
// Create a new calculator
let calc = new_calculator();
println("Created a new calculator with value: " + calc.value);
// Perform some calculations
calc.add(5);
println("After adding 5: " + calc.value);
calc.multiply(2);
println("After multiplying by 2: " + calc.value);
calc.subtract(3);
println("After subtracting 3: " + calc.value);
calc.divide(2);
println("After dividing by 2: " + calc.value);
// Set value directly
calc.value = 100;
println("After setting value to 100: " + calc.value);
// Clear the calculator
calc.clear();
println("After clearing: " + calc.value);
// Chain operations
let result = calc.add(10).multiply(2).subtract(5).divide(3);
println("Result of chained operations: " + result);
println("Final calculator value: " + calc.value);

View File

@@ -0,0 +1,97 @@
use rhai::{Engine, EvalAltResult, CustomType, TypeBuilder};
use rhai_autobind_macros::rhai_model_export;
use serde::{Deserialize, Serialize};
use std::path::Path;
// Dummy DB type for the example, as rhai_model_export requires a db_type
struct DummyDb;
impl DummyDb {
fn new() -> Self { DummyDb }
}
// Define a simple Calculator struct with the rhai_autobind attribute
#[derive(Debug, Clone, Serialize, Deserialize, rhai::CustomType)]
#[rhai_model_export(db_type = "DummyDb")] // Provide the required db_type
pub struct Calculator {
pub value: f64,
}
impl Calculator {
// Constructor
pub fn new() -> Self {
Calculator { value: 0.0 }
}
// Add method
pub fn add(&mut self, x: f64) -> f64 {
self.value += x;
self.value
}
// Subtract method
pub fn subtract(&mut self, x: f64) -> f64 {
self.value -= x;
self.value
}
// Multiply method
pub fn multiply(&mut self, x: f64) -> f64 {
self.value *= x;
self.value
}
// Divide method
pub fn divide(&mut self, x: f64) -> f64 {
if x == 0.0 {
println!("Error: Division by zero!");
return self.value;
}
self.value /= x;
self.value
}
// Clear method
pub fn clear(&mut self) -> f64 {
self.value = 0.0;
self.value
}
// Get value method
pub fn get_value(&self) -> f64 {
self.value
}
}
fn main() -> Result<(), Box<EvalAltResult>> {
println!("Rhai Calculator Example");
println!("======================");
// Create a new Rhai engine
let mut engine = Engine::new();
// Register the Calculator type with the engine using the generated function
let dummy_db = DummyDb::new(); // Create an instance of the dummy DB
Calculator::register_rhai_bindings_for_calculator(&mut engine, dummy_db);
// Register print function for output
engine.register_fn("println", |s: &str| println!("{}", s));
// Create a calculator instance to demonstrate it works
let calc = Calculator::new();
println!("Initial value: {}", calc.value);
// Load and run the Rhai script
let script_path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("examples")
.join("rhai_autobind_example")
.join("calculator.rhai");
println!("Loading Rhai script from: {}", script_path.display());
match engine.eval_file::<()>(script_path) {
Ok(_) => println!("Script executed successfully"),
Err(e) => eprintln!("Error executing script: {}\nAt: {:?}", e, e.position()),
}
Ok(())
}

View File

@@ -0,0 +1,152 @@
use proc_macro::TokenStream;
use quote::{quote, format_ident};
use syn::{parse_macro_input, Ident, Fields, Visibility, ItemStruct, LitStr, ExprArray, Expr, Lit};
use syn::spanned::Spanned; // Add the Spanned trait for span() method
use heck::ToSnakeCase; // For converting struct name to snake_case for function names
#[derive(Debug)]
struct MacroArgs {
db_type: syn::Type,
collection_name: Option<String>,
methods: Vec<String>, // To store method names to be registered
}
impl syn::parse::Parse for MacroArgs {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut db_type_str: Option<LitStr> = None;
let mut collection_name_str: Option<LitStr> = None;
let mut methods_array: Option<ExprArray> = None;
while !input.is_empty() {
let ident: Ident = input.parse()?;
let _eq_token: syn::token::Eq = input.parse()?;
if ident == "db_type" {
db_type_str = Some(input.parse()?);
} else if ident == "collection_name" {
collection_name_str = Some(input.parse()?);
} else if ident == "methods" {
methods_array = Some(input.parse()?);
} else {
return Err(syn::Error::new(ident.span(), "Unknown attribute argument"));
}
if !input.is_empty() {
let _comma: syn::token::Comma = input.parse()?;
}
}
let db_type_str = db_type_str.ok_or_else(|| syn::Error::new(input.span(), "Missing required attribute `db_type`"))?;
let db_type: syn::Type = syn::parse_str(&db_type_str.value())?;
let collection_name = collection_name_str.map(|s| s.value());
let mut methods = Vec::new();
if let Some(array_expr) = methods_array {
for expr in array_expr.elems {
if let Expr::Lit(expr_lit) = expr {
if let Lit::Str(lit_str) = expr_lit.lit {
methods.push(lit_str.value());
} else {
return Err(syn::Error::new(expr_lit.lit.span(), "Method name must be a string literal"));
}
} else {
return Err(syn::Error::new(expr.span(), "Method name must be a string literal"));
}
}
}
Ok(MacroArgs { db_type, collection_name, methods })
}
}
#[proc_macro_attribute]
pub fn rhai_model_export(attr: TokenStream, item: TokenStream) -> TokenStream {
let macro_args = parse_macro_input!(attr as MacroArgs);
let input_struct = parse_macro_input!(item as ItemStruct);
let struct_name = &input_struct.ident;
let struct_name_str = struct_name.to_string();
let struct_name_snake_case = struct_name_str.to_snake_case(); // Use heck for snake_case
let db_type = macro_args.db_type;
let collection_name = macro_args.collection_name.unwrap_or_else(|| {
// Basic pluralization
if struct_name_snake_case.ends_with('y') {
format!("{}ies", &struct_name_snake_case[..struct_name_snake_case.len()-1])
} else if struct_name_snake_case.ends_with('s') {
format!("{}es", struct_name_snake_case)
} else {
format!("{}s", struct_name_snake_case)
}
});
let generated_registration_fn_name = format_ident!("register_rhai_bindings_for_{}", struct_name_snake_case);
let constructor_fn_name = format!("new_{}", struct_name_snake_case);
let mut field_registrations = Vec::new();
if let Fields::Named(fields) = &input_struct.fields {
for field in fields.named.iter() {
if let (Some(field_name), Visibility::Public(_)) = (&field.ident, &field.vis) {
let field_name_str = field_name.to_string();
let field_type = &field.ty;
// Register getter
field_registrations.push(quote! {
engine.register_get(#field_name_str, |s: &mut #struct_name| s.#field_name.clone());
});
// Register setter
field_registrations.push(quote! {
engine.register_set(#field_name_str, |s: &mut #struct_name, val: #field_type| s.#field_name = val);
});
}
}
}
let mut method_registrations = Vec::new();
for method_name_str in &macro_args.methods {
let method_ident = format_ident!("{}", method_name_str);
let rhai_method_name = method_name_str.clone(); // Rhai function name can be the same as Rust method name
method_registrations.push(quote! {
engine.register_fn(#rhai_method_name, #struct_name::#method_ident);
});
}
// Create a formatted string of method names for printing
let methods_str = format!("{:?}", macro_args.methods);
let output = quote! {
#input_struct // Re-emit the original struct definition
impl #struct_name {
pub fn #generated_registration_fn_name(
engine: &mut rhai::Engine,
db: #db_type // db is now passed but not used by default for non-DB methods
) {
// For rhai_wrapper if/when DB operations are added
// use rhai_wrapper::*;
engine.build_type::<#struct_name>();
// Register constructor (e.g., new_calculator for Calculator::new())
engine.register_fn(#constructor_fn_name, #struct_name::new);
// Register field getters and setters
#(#field_registrations)*
// Register specified instance methods
#(#method_registrations)*
// Placeholder for DB function registrations
// e.g., get_by_id, get_all, save, delete
println!("Registered {} with Rhai (collection: '{}'). Constructor: '{}'. Methods: {}. Fields accessible.",
#struct_name_str,
#collection_name,
#constructor_fn_name,
#methods_str
);
}
}
};
TokenStream::from(output)
}