1use saphyr::LoadableYamlNode;
2use std::cell::RefCell;
3use std::rc::Rc;
4
5use crate::Error;
6use crate::Result;
7use crate::RootSchema;
8use crate::Schema;
9use crate::validation::Context;
10
11#[derive(Debug)]
12pub struct Engine<'a> {
13 pub root_schema: &'a RootSchema,
14 pub context: Rc<RefCell<Context<'a>>>,
15}
16
17impl<'a> Engine<'a> {
18 pub fn new(root_schema: &'a RootSchema, context: Context<'a>) -> Self {
19 Engine {
20 root_schema,
21 context: Rc::new(RefCell::new(context)),
22 }
23 }
24
25 pub fn evaluate<'b: 'a>(
26 root_schema: &'b RootSchema,
27 value: &str,
28 fail_fast: bool,
29 ) -> Result<Context<'b>> {
30 let context = Context::with_root_schema(root_schema, fail_fast);
31 let engine = Engine::new(root_schema, context);
32 let docs = saphyr::MarkedYaml::load_from_str(value).map_err(Error::YamlParsingError)?;
33 if docs.is_empty() {
34 if let Some(sub_schema) = &engine.root_schema.schema.as_ref().schema {
35 match sub_schema {
36 Schema::Empty => (),
37 Schema::BooleanLiteral(false) => {
38 engine
39 .context
40 .borrow_mut()
41 .add_doc_error("Empty YAML document is not allowed");
42 }
43 Schema::BooleanLiteral(true) => (),
44 _ => engine
45 .context
46 .borrow_mut()
47 .add_doc_error("Empty YAML document is not allowed"),
48 }
49 }
50 } else {
51 let yaml = docs.first().unwrap();
52 engine
53 .root_schema
54 .validate(&engine.context.borrow(), yaml)?;
55 }
56 Ok(engine.context.take())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use crate::YamlSchema;
64
65 #[test]
66 fn test_engine_empty_schema() {
67 let root_schema = RootSchema::new(YamlSchema::empty());
68 let context = Engine::evaluate(&root_schema, "", false).unwrap();
69 assert!(!context.has_errors());
70 }
71
72 #[test]
73 fn test_engine_boolean_literal_true() {
74 let root_schema = RootSchema::new(YamlSchema::boolean_literal(true));
75 let context = Engine::evaluate(&root_schema, "", false).unwrap();
76 assert!(!context.has_errors());
77 }
78
79 #[test]
80 fn test_engine_boolean_literal_false() {
81 let root_schema = RootSchema::new(YamlSchema::boolean_literal(false));
82 let context = Engine::evaluate(&root_schema, "", false).unwrap();
83 assert!(context.has_errors());
84 }
85}