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
62
63
64
65
66
67
68
//! 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 DummyContext {
        #![allow(clippy::new_without_default)]
        pub fn new() -> DummyContext {
            DummyContext {}
        }
    }

    impl LookupContext for DummyContext {
        fn lookup_rule<'a>(&'a self, name: &str) -> LookupResult<'a> {
            Err(ValidateError::MissingRule(name.into()))
        }
    }
}