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 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) => match engine.root_schema.validate(&engine.context, yaml) {
49 Ok(()) | Err(Error::FailFast) => {}
50 Err(e) => return Err(e),
51 },
52 None => match &engine.root_schema.schema {
53 YamlSchema::Empty | YamlSchema::BooleanLiteral(true) => (),
54 _ => engine
55 .context
56 .add_doc_error("Empty YAML document is not allowed"),
57 },
58 }
59 Ok(engine.context)
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use crate::YamlSchema;
67
68 #[test]
69 fn test_engine_empty_schema() {
70 let root_schema = RootSchema::new(YamlSchema::Empty);
71 let context = Engine::evaluate(&root_schema, "", false).unwrap();
72 assert!(!context.has_errors());
73 }
74
75 #[test]
76 fn test_engine_boolean_literal_true() {
77 let root_schema = RootSchema::new(YamlSchema::BooleanLiteral(true));
78 let context = Engine::evaluate(&root_schema, "", false).unwrap();
79 assert!(!context.has_errors());
80 }
81
82 #[test]
83 fn test_engine_boolean_literal_false() {
84 let root_schema = RootSchema::new(YamlSchema::BooleanLiteral(false));
85 let context = Engine::evaluate(&root_schema, "", false).unwrap();
86 assert!(context.has_errors());
87 }
88}