use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use serde_json::Value;
use crate::error::{ErrorIterator, ValidationError};
use crate::node::SchemaNode;
use crate::paths::LazyLocation;
use super::{Validate, ValidationContext};
pub struct DependentSchemasValidator {
dependencies: BTreeMap<String, SchemaNode>,
}
impl DependentSchemasValidator {
#[must_use]
pub fn new(dependencies: BTreeMap<String, SchemaNode>) -> Self {
Self { dependencies }
}
}
impl Validate for DependentSchemasValidator {
fn is_valid(&self, instance: &Value, ctx: &mut ValidationContext) -> bool {
if let Value::Object(obj) = instance {
for (name, schema) in &self.dependencies {
if obj.contains_key(name) {
let state = ctx.save_evaluation_state();
if !schema.is_valid(instance, ctx) {
ctx.restore_evaluation_state(&state);
return false;
}
}
}
}
true
}
fn validate(
&self,
instance: &Value,
instance_path: &LazyLocation<'_>,
ctx: &mut ValidationContext,
) -> Result<(), ValidationError> {
if let Value::Object(obj) = instance {
for (name, schema) in &self.dependencies {
if obj.contains_key(name) {
let state = ctx.save_evaluation_state();
if let Err(e) = schema.validate(instance, instance_path, ctx) {
ctx.restore_evaluation_state(&state);
return Err(e);
}
}
}
}
Ok(())
}
fn iter_errors(
&self,
instance: &Value,
instance_path: &LazyLocation<'_>,
ctx: &mut ValidationContext,
) -> ErrorIterator {
let mut errors: Vec<ValidationError> = Vec::new();
if let Value::Object(obj) = instance {
for (name, schema) in &self.dependencies {
if obj.contains_key(name) {
let state = ctx.save_evaluation_state();
let sub_errors: Vec<ValidationError> =
schema.iter_errors(instance, instance_path, ctx).collect();
if sub_errors.is_empty() {
} else {
ctx.restore_evaluation_state(&state);
errors.extend(sub_errors);
}
}
}
}
Box::new(errors.into_iter())
}
}