Phase 1.2-1.6: replace variables HashMap<String,String> with HashMap<String,Value>, rewrite str_to_dyn/dyn_to_str -> value_to_dynamic/dynamic_to_value, update resolve_string/evaluate_condition/is_truthy for Value

This commit is contained in:
Glint Dev
2026-07-21 20:32:29 +03:00
parent 5597f07787
commit 30cf2e5e26
7 changed files with 542 additions and 53 deletions

View File

@@ -2,6 +2,9 @@ use rhai::{Dynamic, Engine, Scope, AST, Module};
use std::collections::HashMap;
use std::cell::RefCell;
use super::types::Value;
use compact_str::CompactString;
pub const RHEI_PREFIX: &str = "__rhei:";
pub struct RheiContext {
@@ -46,24 +49,24 @@ impl RheiContext {
}
}
pub fn sync_scope(&self, variables: &HashMap<String, String>) {
pub fn sync_scope(&self, variables: &HashMap<String, Value>) {
let mut scope = self.scope.borrow_mut();
for (k, v) in variables.iter() {
if scope.contains(k) {
if let Some(old_val) = scope.get_value::<Dynamic>(k) {
if dyn_to_str(&old_val) == *v {
if dynamic_to_value(&old_val) == *v {
continue;
}
}
scope.set_value(k, str_to_dyn(v));
scope.set_value(k, value_to_dynamic(v));
} else {
scope.push_dynamic(k.clone(), str_to_dyn(v));
scope.push_dynamic(k.clone(), value_to_dynamic(v));
}
}
}
pub fn initialize(&self, variables: &mut HashMap<String, String>) {
pub fn initialize(&self, variables: &mut HashMap<String, Value>) {
self.sync_scope(variables);
let mut scope = self.scope.borrow_mut();
@@ -72,27 +75,27 @@ impl RheiContext {
}
for (name, _, val) in scope.iter_raw() {
let s_val = dyn_to_str(&val);
let s_val = dynamic_to_value(&val);
if variables.get(name).map(|v| v != &s_val).unwrap_or(true) {
variables.insert(name.to_string(), s_val);
}
}
}
pub fn eval_expr(&self, expr: &str, variables: &HashMap<String, String>) -> String {
pub fn eval_expr(&self, expr: &str, variables: &HashMap<String, Value>) -> Value {
self.sync_scope(variables);
let mut scope = self.scope.borrow_mut();
match self.engine.eval_expression_with_scope::<Dynamic>(&mut *scope, expr) {
Ok(val) => dyn_to_str(&val),
Ok(val) => dynamic_to_value(&val),
Err(e) => {
eprintln!("⚠️ Rhei eval_expr error: {e}");
String::new()
Value::None
}
}
}
pub fn eval_condition(&self, expr: &str, variables: &HashMap<String, String>) -> bool {
pub fn eval_condition(&self, expr: &str, variables: &HashMap<String, Value>) -> bool {
self.sync_scope(variables);
let mut scope = self.scope.borrow_mut();
@@ -105,7 +108,7 @@ impl RheiContext {
}
}
pub fn execute_action(&self, script: &str, variables: &mut HashMap<String, String>) {
pub fn execute_action(&self, script: &str, variables: &mut HashMap<String, Value>) {
self.sync_scope(variables);
let mut scope = self.scope.borrow_mut();
@@ -121,7 +124,7 @@ impl RheiContext {
}
for (name, _, val) in scope.iter_raw() {
let s_val = dyn_to_str(&val);
let s_val = dynamic_to_value(&val);
if variables.get(name).map(|v| v != &s_val).unwrap_or(true) {
variables.insert(name.to_string(), s_val);
}
@@ -135,16 +138,36 @@ impl Default for RheiContext {
}
}
pub fn str_to_dyn(s: &str) -> Dynamic {
if let Ok(i) = s.parse::<i64>() { return Dynamic::from(i); }
if let Ok(f) = s.parse::<f64>() { return Dynamic::from(f); }
if let Ok(b) = s.parse::<bool>() { return Dynamic::from(b); }
Dynamic::from(s.to_owned())
pub fn value_to_dynamic(v: &Value) -> Dynamic {
match v {
Value::Int(i) => Dynamic::from(*i),
Value::Float(f) => Dynamic::from(*f),
Value::Bool(b) => Dynamic::from(*b),
Value::Str(s) => Dynamic::from(s.to_string()),
Value::None => Dynamic::UNIT,
Value::Array(arr) => {
let d: rhai::Dynamic = arr.iter().map(value_to_dynamic).collect();
d
}
}
}
pub fn dyn_to_str(d: &Dynamic) -> String {
pub fn dynamic_to_value(d: &Dynamic) -> Value {
if d.is_string() {
return d.clone().into_string().unwrap_or_default();
return Value::Str(CompactString::new(d.clone().into_string().unwrap_or_default()));
}
d.to_string()
if d.is_int() {
return Value::Int(d.as_int().unwrap_or(0));
}
if d.is_float() {
return Value::Float(d.as_float().unwrap_or(0.0));
}
if d.is_bool() {
return Value::Bool(d.as_bool().unwrap_or(false));
}
if d.is_array() {
let arr = d.clone().into_array().unwrap_or_default();
return Value::Array(arr.iter().map(dynamic_to_value).collect());
}
Value::None
}