tier 0.1.17

Rust configuration library for layered TOML, env, and CLI settings
Documentation
use std::collections::BTreeSet;

use serde_json::Value;

use super::example_matches_schema;

pub(super) fn combinators_match_schema(
    value: &Value,
    object: &serde_json::Map<String, Value>,
    root: &Value,
    visited_refs: &BTreeSet<String>,
) -> bool {
    all_of_matches(value, object, root, visited_refs)
        && any_of_matches(value, object, root, visited_refs)
        && one_of_matches(value, object, root, visited_refs)
        && not_matches(value, object, root, visited_refs)
}

fn all_of_matches(
    value: &Value,
    object: &serde_json::Map<String, Value>,
    root: &Value,
    visited_refs: &BTreeSet<String>,
) -> bool {
    object
        .get("allOf")
        .and_then(Value::as_array)
        .is_none_or(|children| {
            children.iter().all(|child| {
                let mut branch_refs = visited_refs.clone();
                example_matches_schema(value, child, root, &mut branch_refs)
            })
        })
}

fn any_of_matches(
    value: &Value,
    object: &serde_json::Map<String, Value>,
    root: &Value,
    visited_refs: &BTreeSet<String>,
) -> bool {
    object
        .get("anyOf")
        .and_then(Value::as_array)
        .is_none_or(|children| {
            children.iter().any(|child| {
                let mut branch_refs = visited_refs.clone();
                example_matches_schema(value, child, root, &mut branch_refs)
            })
        })
}

fn one_of_matches(
    value: &Value,
    object: &serde_json::Map<String, Value>,
    root: &Value,
    visited_refs: &BTreeSet<String>,
) -> bool {
    object
        .get("oneOf")
        .and_then(Value::as_array)
        .is_none_or(|children| {
            children
                .iter()
                .filter(|child| {
                    let mut branch_refs = visited_refs.clone();
                    example_matches_schema(value, child, root, &mut branch_refs)
                })
                .take(2)
                .count()
                == 1
        })
}

fn not_matches(
    value: &Value,
    object: &serde_json::Map<String, Value>,
    root: &Value,
    visited_refs: &BTreeSet<String>,
) -> bool {
    object.get("not").is_none_or(|child| {
        let mut branch_refs = visited_refs.clone();
        !example_matches_schema(value, child, root, &mut branch_refs)
    })
}