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) => {
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}