Skip to main content

yaml_schema/
validation.rs

1//! The validation module contains the logic for validating a YAML schema against a YAML value
2
3use saphyr::Marker;
4
5use crate::Result;
6
7mod context;
8mod objects;
9mod strings;
10
11pub use context::Context;
12
13/// A trait for validating a sahpyr::Yaml value against a schema
14pub trait Validator {
15    fn validate(&self, context: &Context, value: &saphyr::MarkedYaml) -> Result<()>;
16}
17
18/// A validation error simply contains a path and an error message
19#[derive(Debug)]
20pub struct ValidationError {
21    /// The path to the value that caused the error
22    pub path: String,
23    /// The line and column of the value that caused the error
24    pub marker: Option<Marker>,
25    /// The error message
26    pub error: String,
27}
28
29/// Display these ValidationErrors as "{path}: {error}"
30impl std::fmt::Display for ValidationError {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        if let Some(marker) = &self.marker {
33            write!(
34                f,
35                "[{}:{}] .{}: {}",
36                marker.line(),
37                marker.col() + 1, // contrary to the documentation, columns are 0-indexed
38                self.path,
39                self.error
40            )
41        } else {
42            write!(f, ".{}: {}", self.path, self.error)
43        }
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use crate::YamlSchema;
51    use saphyr::LoadableYamlNode;
52
53    #[test]
54    fn test_validate_empty_schema() {
55        let schema = YamlSchema::Empty;
56        let context = Context::default();
57        let docs = saphyr::MarkedYaml::load_from_str("value").unwrap();
58        let value = docs.first().unwrap();
59        let result = schema.validate(&context, value);
60        assert!(result.is_ok());
61        assert!(!context.has_errors());
62    }
63
64    #[test]
65    fn test_validate_null() {
66        let schema = YamlSchema::Null;
67        let context = Context::default();
68        let docs = saphyr::MarkedYaml::load_from_str("value").unwrap();
69        let value = docs.first().unwrap();
70        let result = schema.validate(&context, value);
71        assert!(result.is_ok());
72        assert!(context.has_errors());
73        let errors = context.errors.borrow();
74        let error = errors.first().unwrap();
75        assert_eq!(error.error, r#"Expected null, but got: "value""#);
76    }
77}