use std::collections::HashMap;
use std::rc::Rc;
use saphyr::LoadableYamlNode;
use crate::Error;
use crate::Result;
use crate::RootSchema;
use crate::Validator as _;
use crate::YamlSchema;
use crate::validation::Context;
#[derive(Debug)]
pub struct Engine<'a> {
pub root_schema: &'a RootSchema,
pub context: Context<'a>,
}
impl<'a> Engine<'a> {
pub fn new(root_schema: &'a RootSchema, context: Context<'a>) -> Self {
Engine {
root_schema,
context,
}
}
pub fn evaluate<'b: 'a>(
root_schema: &'b RootSchema,
value: &str,
fail_fast: bool,
) -> Result<Context<'b>> {
Self::evaluate_with_schemas(root_schema, value, fail_fast, HashMap::new())
}
pub fn evaluate_with_schemas<'b: 'a>(
root_schema: &'b RootSchema,
value: &str,
fail_fast: bool,
preloaded_schemas: HashMap<String, Rc<RootSchema>>,
) -> Result<Context<'b>> {
let context =
Context::with_root_schema_and_schemas(root_schema, fail_fast, preloaded_schemas);
let engine = Engine::new(root_schema, context);
let docs = saphyr::MarkedYaml::load_from_str(value).map_err(Error::YamlParsingError)?;
match docs.first() {
Some(yaml) => {
engine.root_schema.validate(&engine.context, yaml)?;
}
None => match &engine.root_schema.schema {
YamlSchema::Empty | YamlSchema::BooleanLiteral(true) => (),
_ => engine
.context
.add_doc_error("Empty YAML document is not allowed"),
},
}
Ok(engine.context)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::YamlSchema;
#[test]
fn test_engine_empty_schema() {
let root_schema = RootSchema::new(YamlSchema::Empty);
let context = Engine::evaluate(&root_schema, "", false).unwrap();
assert!(!context.has_errors());
}
#[test]
fn test_engine_boolean_literal_true() {
let root_schema = RootSchema::new(YamlSchema::BooleanLiteral(true));
let context = Engine::evaluate(&root_schema, "", false).unwrap();
assert!(!context.has_errors());
}
#[test]
fn test_engine_boolean_literal_false() {
let root_schema = RootSchema::new(YamlSchema::BooleanLiteral(false));
let context = Engine::evaluate(&root_schema, "", false).unwrap();
assert!(context.has_errors());
}
}