Skip to main content

yaml_schema/
engine.rs

1use std::collections::HashMap;
2use std::rc::Rc;
3
4use saphyr::LoadableYamlNode;
5
6use crate::Error;
7use crate::Result;
8use crate::RootSchema;
9use crate::Validator as _;
10use crate::YamlSchema;
11use crate::validation::Context;
12
13#[derive(Debug)]
14pub struct Engine<'a> {
15    pub root_schema: &'a RootSchema,
16    pub context: Context<'a>,
17}
18
19impl<'a> Engine<'a> {
20    pub fn new(root_schema: &'a RootSchema, context: Context<'a>) -> Self {
21        Engine {
22            root_schema,
23            context,
24        }
25    }
26
27    pub fn evaluate<'b: 'a>(
28        root_schema: &'b RootSchema,
29        value: &str,
30        fail_fast: bool,
31    ) -> Result<Context<'b>> {
32        Self::evaluate_with_schemas(root_schema, value, fail_fast, HashMap::new())
33    }
34
35    /// Evaluate with pre-loaded schemas (e.g. from multiple -f flags).
36    /// Schemas are keyed by document URI (file:// or https://).
37    pub fn evaluate_with_schemas<'b: 'a>(
38        root_schema: &'b RootSchema,
39        value: &str,
40        fail_fast: bool,
41        preloaded_schemas: HashMap<String, Rc<RootSchema>>,
42    ) -> Result<Context<'b>> {
43        let context =
44            Context::with_root_schema_and_schemas(root_schema, fail_fast, preloaded_schemas);
45        let engine = Engine::new(root_schema, context);
46        let docs = saphyr::MarkedYaml::load_from_str(value).map_err(Error::YamlParsingError)?;
47        match docs.first() {
48            Some(yaml) => {
49                engine.root_schema.validate(&engine.context, yaml)?;
50            }
51            None => match &engine.root_schema.schema {
52                YamlSchema::Empty | YamlSchema::BooleanLiteral(true) => (),
53                _ => engine
54                    .context
55                    .add_doc_error("Empty YAML document is not allowed"),
56            },
57        }
58        Ok(engine.context)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use crate::YamlSchema;
66
67    #[test]
68    fn test_engine_empty_schema() {
69        let root_schema = RootSchema::new(YamlSchema::Empty);
70        let context = Engine::evaluate(&root_schema, "", false).unwrap();
71        assert!(!context.has_errors());
72    }
73
74    #[test]
75    fn test_engine_boolean_literal_true() {
76        let root_schema = RootSchema::new(YamlSchema::BooleanLiteral(true));
77        let context = Engine::evaluate(&root_schema, "", false).unwrap();
78        assert!(!context.has_errors());
79    }
80
81    #[test]
82    fn test_engine_boolean_literal_false() {
83        let root_schema = RootSchema::new(YamlSchema::BooleanLiteral(false));
84        let context = Engine::evaluate(&root_schema, "", false).unwrap();
85        assert!(context.has_errors());
86    }
87}