use std::collections::HashMap; use crate::database::object::{is_primitive_type, SchemaTypeOrArray}; use crate::database::schema::Schema; use crate::validator::context::ValidationContext; use crate::validator::error::ValidationError; use crate::validator::result::ValidationResult; impl<'a> ValidationContext<'a> { pub(crate) fn validate_extensible(&self, result: &mut ValidationResult) -> Result { if self.extensible { if let Some(obj) = self.instance.as_object() { result.evaluated_keys.extend(obj.keys().cloned()); } else if let Some(arr) = self.instance.as_array() { result.evaluated_indices.extend(0..arr.len()); } } Ok(true) } pub(crate) fn schema_expects_primitive(&self, schema: &Schema, primitive: &str) -> bool { match &schema.type_ { None => true, // Any type is allowed Some(SchemaTypeOrArray::Single(t)) => { if t == primitive { true } else if !is_primitive_type(t) { if primitive == "object" { true } else { // Custom type - resolve recursively if let Some(parent) = self.db.schemas.get(t) { self.schema_expects_primitive(parent, primitive) } else { false } } } else { false } } Some(SchemaTypeOrArray::Multiple(types)) => { types.iter().any(|t| { if t == primitive { true } else if !is_primitive_type(t) { if primitive == "object" { true } else { if let Some(parent) = self.db.schemas.get(t) { self.schema_expects_primitive(parent, primitive) } else { false } } } else { false } }) } } } pub(crate) fn validate_strictness( &self, result: &mut ValidationResult, ) -> Result { if self.extensible || self.reporter { return Ok(true); } if self.schema_expects_primitive(self.schema, "object") || self.schema_expects_primitive(self.schema, "dict") { if let Some(obj) = self.instance.as_object() { for key in obj.keys() { if !result.evaluated_keys.contains(key) && !self.overrides.contains(key) { result.errors.push(ValidationError { code: "STRICT_PROPERTY_VIOLATION".to_string(), values: Some(HashMap::from([ ("property_name".to_string(), key.to_string()), ])), path: self.join_path(key), }); } } } } Ok(true) } }