use std::collections::HashSet; use serde_json::Value; use crate::validator::context::ValidationContext; use crate::validator::error::ValidationError; use crate::validator::result::ValidationResult; impl<'a> ValidationContext<'a> { pub(crate) fn validate_array( &self, result: &mut ValidationResult, ) -> Result { let current = self.instance; if let Some(arr) = current.as_array() { if let Some(min) = self.schema.min_items && (arr.len() as f64) < min { result.errors.push(ValidationError { code: "MIN_ITEMS".to_string(), message: "Too few items".to_string(), path: self.path.to_string(), }); } if let Some(max) = self.schema.max_items && (arr.len() as f64) > max { result.errors.push(ValidationError { code: "MAX_ITEMS".to_string(), message: "Too many items".to_string(), path: self.path.to_string(), }); } if self.schema.unique_items.unwrap_or(false) { let mut seen: Vec<&Value> = Vec::new(); for item in arr { if seen.contains(&item) { result.errors.push(ValidationError { code: "UNIQUE_ITEMS_VIOLATED".to_string(), message: "Array has duplicate items".to_string(), path: self.path.to_string(), }); break; } seen.push(item); } } if let Some(ref contains_schema) = self.schema.contains { let mut _match_count = 0; for (i, child_instance) in arr.iter().enumerate() { let derived = self.derive( contains_schema, child_instance, &self.path, HashSet::new(), self.extensible, false, ); let check = derived.validate()?; if check.is_valid() { _match_count += 1; result.evaluated_indices.insert(i); } } let min = self.schema.min_contains.unwrap_or(1.0) as usize; if _match_count < min { result.errors.push(ValidationError { code: "CONTAINS_VIOLATED".to_string(), message: format!("Contains matches {} < min {}", _match_count, min), path: self.path.to_string(), }); } if let Some(max) = self.schema.max_contains && _match_count > max as usize { result.errors.push(ValidationError { code: "CONTAINS_VIOLATED".to_string(), message: format!("Contains matches {} > max {}", _match_count, max), path: self.path.to_string(), }); } } let len = arr.len(); let mut validation_index = 0; if let Some(ref prefix) = self.schema.prefix_items { for (i, sub_schema) in prefix.iter().enumerate() { if i < len { let path = format!("{}/{}", self.path, i); if let Some(child_instance) = arr.get(i) { let derived = self.derive( sub_schema, child_instance, &path, HashSet::new(), self.extensible, false, ); let item_res = derived.validate()?; result.merge(item_res); result.evaluated_indices.insert(i); validation_index += 1; } } } } if let Some(ref items_schema) = self.schema.items { for i in validation_index..len { let path = format!("{}/{}", self.path, i); if let Some(child_instance) = arr.get(i) { let derived = self.derive( items_schema, child_instance, &path, HashSet::new(), self.extensible, false, ); let item_res = derived.validate()?; result.merge(item_res); result.evaluated_indices.insert(i); } } } } Ok(true) } }