use std::collections::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; pub struct Validator { pub db: Arc, } impl Validator { pub fn new(db: Arc) -> Self { Self { db } } pub fn get_schema_ids(&self) -> Vec { self.db.schemas.keys().cloned().collect() } 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 { if let Some(schema) = self.db.schemas.get(schema_id) { let ctx = ValidationContext::new( &self.db, schema, schema, instance, HashSet::new(), false, false, ); match ctx.validate_scoped() { Ok(result) => { if result.is_valid() { crate::drop::Drop::success() } else { let errors: Vec = result .errors .into_iter() .map(|e| crate::drop::Error { code: e.code, message: e.message, details: crate::drop::ErrorDetails { path: e.path, cause: None, context: None, schema: None, }, }) .collect(); crate::drop::Drop::with_errors(errors) } } Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { code: e.code, message: e.message, details: crate::drop::ErrorDetails { path: e.path, cause: None, context: None, schema: None, }, }]), } } else { crate::drop::Drop::with_errors(vec![crate::drop::Error { code: "SCHEMA_NOT_FOUND".to_string(), message: format!("Schema {} not found", schema_id), details: crate::drop::ErrorDetails { path: "/".to_string(), cause: None, context: None, schema: None, }, }]) } } }