91 lines
2.7 KiB
Rust
91 lines
2.7 KiB
Rust
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<bool, ValidationError> {
|
|
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<bool, ValidationError> {
|
|
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)
|
|
}
|
|
}
|