//! Invoke a registered validator by its id.
//!
//! Walks `inventory::iter::<ValidatorEntry>()` (constant-time after the
//! first call thanks to `inventory`'s static initialisation) and calls
//! the matching predicate. Returns `None` when no entry matches; the
//! caller decides whether `None` is a hard error (typo in catalog) or
//! soft (validator not yet implemented).

use crate::validation::registry::ValidatorEntry;
use crate::validation::traits::{Slice, ValidationCtx};
use crate::validation::verdict::Verdict;

/// Invoke the validator registered under `id`. Returns the verdict, or
/// `None` if no validator with that id is in the inventory.
pub fn dispatch(id: &str, slice: &Slice, ctx: &ValidationCtx) -> Option<Verdict> {
    let entry = inventory::iter::<ValidatorEntry>().find(|e| e.id == id)?;
    Some((entry.predicate)(slice, ctx))
}

/// Snapshot of every registered validator id. Useful for diagnostics
/// (e.g. `ontoref validators list`) and tests.
pub fn registered_ids() -> Vec<&'static str> {
    inventory::iter::<ValidatorEntry>().map(|e| e.id).collect()
}
