use crate::parser::types::{Value, FunctionValue};
use crate::parser::interpreter::{Interpreter, DynamicFn, DynamicFnInfo};
use std::sync::{Arc, Mutex};
fn check_rec(schema: &Value, val: &Value) -> bool {
match schema {
Value::SingleString(tname) => match tname.as_str() {
"int" => matches!(val, Value::Int(_)),
"long" => matches!(val, Value::Long(_)),
"float" => matches!(val, Value::Float(_)),
"bool" => matches!(val, Value::Bool(_)),
"string" => matches!(val, Value::SingleString(_)),
"int_array" => matches!(val, Value::IntArray(_)),
"float_array" => matches!(val, Value::FloatArray(_)),
"str_array" => matches!(val, Value::StrArray(_)),
"mixed_array" => matches!(val, Value::MixedArray(_)),
_ => false,
},
Value::StrArray(schema_arr) if schema_arr.len() == 1 => match schema_arr[0].as_str() {
"int" => matches!(val, Value::IntArray(_)),
"float" => matches!(val, Value::FloatArray(_)),
"string" => matches!(val, Value::StrArray(_)),
"mixed" => matches!(val, Value::MixedArray(_)),
_ => false,
},
Value::KeyedArray(schema_map) => {
if let Value::KeyedArray(val_map) = val {
for (k, sch_v) in schema_map {
if let Some(val_v) = val_map.get(k) {
if !check_rec(sch_v, val_v) {
return false;
}
} else {
return false;
}
}
true
} else {
false
}
}
Value::MixedArray(schema_items) if schema_items.len() == 1 => {
let item_schema = &schema_items[0];
if let Value::MixedArray(vals) = val {
for item in vals {
if !check_rec(item_schema, item) {
return false;
}
}
true
} else {
false
}
}
_ => false,
}
}
fn check_bridge(
_interp: &mut Interpreter,
args: Vec<Value>
) -> Result<Value, String> {
if args.len() != 2 {
return Err("check(schema, value) expects 2 arguments".into());
}
let schema = &args[0];
let value = &args[1];
let ok = check_rec(schema, value);
Ok(Value::Bool(ok))
}
pub fn register_check(interp: &mut Interpreter) {
let f: DynamicFn = Arc::new(Mutex::new(check_bridge));
let info = DynamicFnInfo::new(f, true);
interp.register_dynamic_function_ex("check", info);
interp.set_variable(
"check",
Value::Function(Box::new(FunctionValue::Named("check".to_string())))
);
}