1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
//! This module defines the LookupContext trait.
//!
//! A [`LookupContext`] is used to specify runtime behavior for validation.
//! When a validation needs to resolve a rule reference, it will ask the
//! `LookupContext` to perform the name resolution.
//!
use crate::ivt::{RuleDef, RulesByName};
use crate::util::ValidateError;
// The Node reference lives as long as the LookupContext does.
type LookupResult<'a> = Result<&'a RuleDef, ValidateError>;
/// A LookupContext contains any external information required for validation.
///
/// Right now, that only includes a function that understands how to resolve
/// a name reference to an [`ivt::Rule`].
///
/// [`ivt::Rule`]: crate::ivt::Rule
pub trait LookupContext {
/// Lookup a rule by name.
fn lookup_rule<'a>(&'a self, name: &str) -> LookupResult<'a>;
}
/// A simple context that owns a set of rules and can lookup rules by name.
#[allow(missing_docs)]
pub struct BasicContext {
pub rules: RulesByName,
}
impl BasicContext {
/// Create a new BasicContext from a rules map.
pub fn new(rules: RulesByName) -> BasicContext {
BasicContext { rules }
}
}
impl LookupContext for BasicContext {
fn lookup_rule<'a>(&'a self, name: &str) -> LookupResult<'a> {
match self.rules.get(name) {
Some(rule_def) => Ok(rule_def),
None => Err(ValidateError::MissingRule(name.into())),
}
}
}
#[doc(hidden)] // Only pub for integration tests
#[allow(missing_docs)]
pub mod tests {
use super::*;
/// A `LookupContext` that fails all rule lookups
pub struct DummyContext;
impl LookupContext for DummyContext {
fn lookup_rule<'a>(&'a self, name: &str) -> LookupResult<'a> {
Err(ValidateError::MissingRule(name.into()))
}
}
}