checkpoint

This commit is contained in:
2026-04-09 18:39:52 -04:00
parent 9387152859
commit 5f45df6c11
11 changed files with 677 additions and 467 deletions

View File

@ -1,4 +1,3 @@
use crate::database::schema::Schema;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
@ -29,30 +28,10 @@ impl<'a> ValidationContext<'a> {
}
}
if let Some(family_target) = &self.schema.family {
if let Some(descendants) = self.db.descendants.get(family_target) {
let mut candidates = Vec::new();
// Add the target base schema itself
if let Some(base_schema) = self.db.schemas.get(family_target) {
candidates.push(base_schema);
}
// Add all descendants
for child_id in descendants {
if let Some(child_schema) = self.db.schemas.get(child_id) {
candidates.push(child_schema);
}
}
// Use prefix from family string (e.g. `light.`)
let prefix = family_target
.rsplit_once('.')
.map(|(p, _)| format!("{}.", p))
.unwrap_or_default();
if !self.validate_polymorph(&candidates, Some(&prefix), result)? {
return Ok(false);
if self.schema.family.is_some() {
if let Some(options) = self.schema.compiled_options.get() {
if let Some(disc) = self.schema.compiled_discriminator.get() {
return self.execute_polymorph(disc, options, result);
}
}
}
@ -64,212 +43,43 @@ impl<'a> ValidationContext<'a> {
&self,
result: &mut ValidationResult,
) -> Result<bool, ValidationError> {
if let Some(ref one_of) = self.schema.one_of {
let mut candidates = Vec::new();
for schema in one_of {
candidates.push(schema.as_ref());
if let Some(one_of) = &self.schema.one_of {
if let Some(options) = self.schema.compiled_options.get() {
if let Some(disc) = self.schema.compiled_discriminator.get() {
return self.execute_polymorph(disc, options, result);
}
}
if !self.validate_polymorph(&candidates, None, result)? {
return Ok(false);
}
}
Ok(true)
}
pub(crate) fn validate_polymorph(
&self,
candidates: &[&Schema],
family_prefix: Option<&str>,
result: &mut ValidationResult,
) -> Result<bool, ValidationError> {
let mut passed_candidates: Vec<(Option<String>, ValidationResult)> = Vec::new();
let mut failed_candidates: Vec<ValidationResult> = Vec::new();
// Native Draft2020-12 oneOf Evaluation Fallback
let mut valid_count = 0;
let mut final_successful_result = None;
let mut failed_candidates = Vec::new();
// 1. O(1) Fast-Path Router & Extractor
let instance_type = self.instance.as_object().and_then(|o| o.get("type")).and_then(|t| t.as_str());
let instance_kind = self.instance.as_object().and_then(|o| o.get("kind")).and_then(|k| k.as_str());
let mut viable_candidates = Vec::new();
for sub in candidates {
let _child_id = sub.identifier().unwrap_or_default();
let mut can_match = true;
if let Some(t) = instance_type {
// Fast Path 1: Pure Ad-Hoc Match (schema identifier == type)
// If it matches exactly, it's our golden candidate. Make all others non-viable manually?
// Wait, we loop through all and filter down. If exact match is found, we should ideally break and use ONLY that.
// Let's implement the logic safely.
let mut exact_match_found = false;
if let Some(schema_id) = &sub.id {
// Compute Vertical Exact Target (e.g. "person" or "light.person")
let exact_target = if let Some(prefix) = family_prefix {
format!("{}{}", prefix, t)
} else {
t.to_string()
};
// Fast Path 1 & 2: Vertical Exact Match
if schema_id == &exact_target {
if instance_kind.is_none() {
exact_match_found = true;
}
}
// Fast Path 3: Horizontal Sibling Match (kind + . + type)
if let Some(k) = instance_kind {
let sibling_target = format!("{}.{}", k, t);
if schema_id == &sibling_target {
exact_match_found = true;
}
}
}
if exact_match_found {
// We found an exact literal structural identity match!
// Wipe the existing viable_candidates and only yield this guy!
viable_candidates.clear();
viable_candidates.push(*sub);
break;
}
// Fast Path 4: Vertical Inheritance Fallback (Physical DB constraint)
if let Some(crate::database::schema::SchemaTypeOrArray::Single(t_ptr)) = &sub.type_ {
if !crate::database::schema::is_primitive_type(t_ptr) {
if let Some(base_type) = t_ptr.split('.').last() {
if let Some(type_def) = self.db.types.get(base_type) {
if !type_def.variations.contains(&t.to_string()) {
can_match = false;
}
} else {
if t_ptr != t {
can_match = false;
}
}
}
}
}
// Fast Path 5: Explicit Schema JSON `const` values check
if can_match {
if let Some(props) = &sub.properties {
if let Some(type_prop) = props.get("type") {
if let Some(const_val) = &type_prop.const_ {
if let Some(const_str) = const_val.as_str() {
if const_str != t {
can_match = false;
}
}
}
}
for child_schema in one_of {
let derived = self.derive_for_schema(child_schema, false);
if let Ok(sub_res) = derived.validate_scoped() {
if sub_res.is_valid() {
valid_count += 1;
final_successful_result = Some(sub_res.clone());
} else {
failed_candidates.push(sub_res);
}
}
}
if can_match {
viable_candidates.push(*sub);
}
}
println!("DEBUG VIABLE: {:?}", viable_candidates.iter().map(|s| s.id.clone()).collect::<Vec<_>>());
// 2. Evaluate Viable Candidates
// 2. Evaluate Viable Candidates
// Composition validation is natively handled directly via type compilation.
// The deprecated allOf JSON structure is no longer supported nor traversed.
for sub in viable_candidates.clone() {
let derived = self.derive_for_schema(sub, false);
let sub_res = derived.validate()?;
if sub_res.is_valid() {
passed_candidates.push((sub.id.clone(), sub_res));
} else {
failed_candidates.push(sub_res);
}
}
for f in &failed_candidates {
println!(" - Failed candidate errors: {:?}", f.errors.iter().map(|e| e.code.clone()).collect::<Vec<_>>());
}
if passed_candidates.len() == 1 {
result.merge(passed_candidates.pop().unwrap().1);
} else if passed_candidates.is_empty() {
// 3. Discriminator Pathing (Failure Analytics)
let type_path = self.join_path("type");
if instance_type.is_some() {
// Filter to candidates that didn't explicitly throw a CONST violation on `type`
let mut genuinely_failed = Vec::new();
for res in &failed_candidates {
let rejected_type = res.errors.iter().any(|e| {
(e.code == "CONST_VIOLATED" || e.code == "ENUM_VIOLATED") && e.path == type_path
});
if !rejected_type {
genuinely_failed.push(res.clone());
}
}
println!("DEBUG genuinely_failed len: {}", genuinely_failed.len());
if genuinely_failed.len() == 1 {
// Golden Type Match (1 candidate was structurally possible but failed property validation)
let sub_res = genuinely_failed.pop().unwrap();
result.errors.extend(sub_res.errors);
result.evaluated_keys.extend(sub_res.evaluated_keys);
return Ok(false);
} else {
// Pure Ad-Hoc Union
result.errors.push(ValidationError {
code: if self.schema.family.is_some() { "NO_FAMILY_MATCH".to_string() } else { "NO_ONEOF_MATCH".to_string() },
message: "Payload matches none of the required candidate sub-schemas".to_string(),
if valid_count == 1 {
if let Some(successful_res) = final_successful_result {
result.merge(successful_res);
}
return Ok(true);
} else if valid_count == 0 {
result.errors.push(ValidationError {
code: "NO_ONEOF_MATCH".to_string(),
message: "Payload matches none of the required candidate sub-schemas natively".to_string(),
path: self.path.to_string(),
});
for sub_res in &failed_candidates {
result.evaluated_keys.extend(sub_res.evaluated_keys.clone());
}
println!("DEBUG ELSE NO_FAMILY_MATCH RUNNING. Genuinely Failed len: {}", genuinely_failed.len());
if viable_candidates.is_empty() {
if let Some(obj) = self.instance.as_object() {
result.evaluated_keys.extend(obj.keys().cloned());
}
}
for sub_res in genuinely_failed {
for e in sub_res.errors {
if !result.errors.iter().any(|existing| existing.code == e.code && existing.path == e.path) {
result.errors.push(e);
}
}
}
return Ok(false);
}
} else {
// Instance missing type
// Instance missing type
let expects_type = viable_candidates.iter().any(|c| {
c.compiled_property_names.get().map_or(false, |props| props.contains(&"type".to_string()))
});
if expects_type {
result.errors.push(ValidationError {
code: "MISSING_TYPE".to_string(),
message: "Missing type discriminator. Unable to resolve polymorphic boundaries".to_string(),
path: self.path.to_string(),
});
for sub_res in failed_candidates {
result.evaluated_keys.extend(sub_res.evaluated_keys);
}
return Ok(false);
} else {
// Pure Ad-Hoc Union
result.errors.push(ValidationError {
code: if self.schema.family.is_some() { "NO_FAMILY_MATCH".to_string() } else { "NO_ONEOF_MATCH".to_string() },
message: "Payload matches none of the required candidate sub-schemas".to_string(),
path: self.path.to_string(),
});
if let Some(first) = failed_candidates.first() {
});
if let Some(first) = failed_candidates.first() {
let mut shared_errors = first.errors.clone();
for sub_res in failed_candidates.iter().skip(1) {
shared_errors.retain(|e1| {
@ -281,26 +91,66 @@ impl<'a> ValidationContext<'a> {
result.errors.push(e);
}
}
}
for sub_res in failed_candidates {
result.evaluated_keys.extend(sub_res.evaluated_keys);
}
return Ok(false);
}
}
return Ok(false);
} else {
result.errors.push(ValidationError {
code: "AMBIGUOUS_POLYMORPHIC_MATCH".to_string(),
message: "Matches multiple polymorphic candidates inextricably natively".to_string(),
path: self.path.to_string(),
});
return Ok(false);
}
} else {
result.errors.push(ValidationError {
code: "AMBIGUOUS_POLYMORPHIC_MATCH".to_string(),
message: "Matches multiple polymorphic candidates inextricably".to_string(),
path: self.path.to_string(),
});
}
Ok(true)
}
pub(crate) fn execute_polymorph(
&self,
disc: &str,
options: &std::collections::BTreeMap<String, String>,
result: &mut ValidationResult,
) -> Result<bool, ValidationError> {
// 1. O(1) Fast-Path Router & Extractor
let instance_val = self.instance.as_object().and_then(|o| o.get(disc)).and_then(|t| t.as_str());
if let Some(val) = instance_val {
result.evaluated_keys.insert(disc.to_string());
if let Some(target_id) = options.get(val) {
if let Some(target_schema) = self.db.schemas.get(target_id) {
let derived = self.derive_for_schema(target_schema, false);
let sub_res = derived.validate()?;
let is_valid = sub_res.is_valid();
result.merge(sub_res);
return Ok(is_valid);
} else {
result.errors.push(ValidationError {
code: "MISSING_COMPILED_SCHEMA".to_string(),
message: format!("Polymorphic router target '{}' does not exist in the database schemas map", target_id),
path: self.path.to_string(),
});
return Ok(false);
}
} else {
result.errors.push(ValidationError {
code: if self.schema.family.is_some() { "NO_FAMILY_MATCH".to_string() } else { "NO_ONEOF_MATCH".to_string() },
message: format!("Payload provided discriminator {}='{}' which matches none of the required candidate sub-schemas", disc, val),
path: self.path.to_string(),
});
return Ok(false);
}
} else {
result.errors.push(ValidationError {
code: "MISSING_TYPE".to_string(),
message: format!("Missing '{}' discriminator. Unable to resolve polymorphic boundaries", disc),
path: self.path.to_string(),
});
return Ok(false);
}
}
pub(crate) fn validate_type_inheritance(
&self,
result: &mut ValidationResult,