yaml_schema/
validation.rs1use log::debug;
2
3use saphyr::Marker;
4
5pub mod any_of;
6mod context;
7mod objects;
8mod one_of;
9mod strings;
10
11use crate::Result;
12use crate::Schema;
13use crate::utils::format_yaml_data;
14
15pub use context::Context;
16
17pub trait Validator {
19 fn validate(&self, context: &Context, value: &saphyr::MarkedYaml) -> Result<()>;
20}
21
22#[derive(Debug)]
24pub struct ValidationError {
25 pub path: String,
27 pub marker: Option<Marker>,
29 pub error: String,
31}
32
33impl std::fmt::Display for ValidationError {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 if let Some(marker) = &self.marker {
37 write!(
38 f,
39 "[{}:{}] .{}: {}",
40 marker.line(),
41 marker.col() + 1, self.path,
43 self.error
44 )
45 } else {
46 write!(f, ".{}: {}", self.path, self.error)
47 }
48 }
49}
50
51impl Validator for Schema {
52 fn validate(&self, context: &Context, value: &saphyr::MarkedYaml) -> Result<()> {
53 debug!("[Schema] self: {self}");
54 debug!(
55 "[Schema] Validating value: {}",
56 format_yaml_data(&value.data)
57 );
58 match self {
59 Schema::Empty => Ok(()),
60 Schema::BooleanLiteral(boolean) => {
61 if !*boolean {
62 context.add_error(value, "Schema is `false`!".to_string());
63 }
64 Ok(())
65 }
66 Schema::Const(const_schema) => const_schema.validate(context, value),
67 Schema::Enum(enum_schema) => enum_schema.validate(context, value),
68 Schema::AllOf(all_of_schema) => all_of_schema.validate(context, value),
69 Schema::AnyOf(any_of_schema) => any_of_schema.validate(context, value),
70 Schema::OneOf(one_of_schema) => one_of_schema.validate(context, value),
71 Schema::Not(not_schema) => not_schema.validate(context, value),
72 Schema::Typed(typed_schema) => typed_schema.validate(context, value),
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::YamlSchema;
81 use saphyr::LoadableYamlNode;
82
83 #[test]
84 fn test_validate_empty_schema() {
85 let schema = YamlSchema::empty();
86 let context = Context::default();
87 let docs = saphyr::MarkedYaml::load_from_str("value").unwrap();
88 let value = docs.first().unwrap();
89 let result = schema.validate(&context, value);
90 assert!(result.is_ok());
91 assert!(!context.has_errors());
92 }
93
94 #[test]
95 fn test_validate_type_null() {
96 let schema = YamlSchema::null();
97 let context = Context::default();
98 let docs = saphyr::MarkedYaml::load_from_str("value").unwrap();
99 let value = docs.first().unwrap();
100 let result = schema.validate(&context, value);
101 assert!(result.is_ok());
102 assert!(context.has_errors());
103 let errors = context.errors.borrow();
104 let error = errors.first().unwrap();
105 assert_eq!(
106 error.error,
107 "Expected null, but got: Value(String(\"value\"))"
108 );
109 }
110}