use std::collections::{HashMap, HashSet}; pub mod context; pub mod error; pub mod result; pub mod rules; pub use context::ValidationContext; pub use error::ValidationError; pub use result::ValidationResult; use crate::database::Database; use crate::validator::rules::util::is_integer; use serde_json::Value; use std::sync::Arc; use crate::drop::{Drop, Error, ErrorDetails}; pub struct Validator { pub db: Arc, } impl Validator { pub fn new(db: Arc) -> Self { Self { db } } pub fn check_type(t: &str, val: &Value) -> bool { if let Value::String(s) = val && s.is_empty() { return true; } match t { "null" => val.is_null(), "boolean" => val.is_boolean(), "string" => val.is_string(), "number" => val.is_number(), "integer" => is_integer(val), "object" => val.is_object(), "array" => val.is_array(), _ => true, } } pub fn validate(&self, schema_id: &str, instance: &Value) -> crate::drop::Drop { let schema_opt = self.db.schemas.get(schema_id); if let Some(schema) = schema_opt { let ctx = ValidationContext::new( &self.db, &schema, &schema, instance, HashSet::new(), false, false, ); match ctx.validate_scoped() { Ok(result) => { if result.is_valid() { Drop::success() } else { let errors: Vec = result .errors .into_iter() .map(|e| Error { code: e.code, values: e.values, details: ErrorDetails { path: Some(e.path), cause: None, context: None, schema: Some(schema_id.to_string()), }, }) .collect(); Drop::with_errors(errors) } } Err(e) => Drop::with_errors(vec![Error { code: e.code, values: e.values, details: ErrorDetails { path: Some(e.path), cause: None, context: None, schema: Some(schema_id.to_string()), }, }]), } } else { Drop::with_errors(vec![Error { code: "SCHEMA_NOT_FOUND".to_string(), values: Some(HashMap::from([ ("schema".to_string(), schema_id.to_string()), ])), details: ErrorDetails { path: Some("/".to_string()), cause: None, context: None, schema: Some(schema_id.to_string()), }, }]) } } }