use crate::config::json::Value as JsonValue;
use std::collections::HashMap;
use std::path::Path;
pub struct SchemaValidator {
schemas: HashMap<String, JsonValue>,
}
impl SchemaValidator {
pub fn new(schemas_dir: &Path) -> Result<Self, String> {
let mut schemas = HashMap::new();
let schema_types = vec!["engine_execution", "comparison_result", "training_sample"];
for schema_type in schema_types {
let schema_path = schemas_dir.join("v1").join(format!("{}.json", schema_type));
match std::fs::read_to_string(&schema_path) {
Ok(schema_content) => match schema_content.parse::<JsonValue>() {
Ok(schema_value) => {
schemas.insert(schema_type.to_string(), schema_value);
}
Err(e) => {
eprintln!("Warning: failed to parse schema {:?}: {}", schema_path, e);
}
},
Err(e) => {
eprintln!("Warning: missing schema {:?}: {}", schema_path, e);
}
}
}
Ok(Self { schemas })
}
pub fn validate(&self, data: &JsonValue, schema_type: &str) -> Result<(), String> {
let schema_value = match self.schemas.get(schema_type) {
Some(s) => s,
None => {
eprintln!(
"[validator] warning: schema not found for {}, permissive mode",
schema_type
);
return Ok(());
}
};
if matches!(data, JsonValue::Null) {
return Err("Payload is null".to_string());
}
if let JsonValue::Object(schema_obj) = schema_value {
if let Some(JsonValue::Array(arr)) = schema_obj.get("required") {
for item in arr.iter() {
if let JsonValue::String(field) = item {
if let JsonValue::Object(dobj) = data {
if !dobj.contains_key(field) {
return Err(format!("Missing required field: {}", field));
}
} else {
return Err("Payload is not an object".to_string());
}
}
}
}
}
Ok(())
}
pub fn validate_or_error(&self, data: &JsonValue, schema_type: &str) -> Result<(), String> {
self.validate(data, schema_type)
.map_err(|e| format!("Validation failed: {}", e))
}
}