yaml_schema/validation/
context.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3
4use crate::RootSchema;
5use crate::YamlSchema;
6use crate::validation::ValidationError;
7
8/// The validation context
9#[derive(Debug, Default)]
10pub struct Context<'r> {
11    /// We use an Option here so tests can be run without a root schema
12    pub root_schema: Option<&'r RootSchema>,
13    pub current_schema: Option<Rc<YamlSchema>>,
14    pub current_path: Vec<String>,
15    pub stream_started: bool,
16    pub stream_ended: bool,
17    pub errors: Rc<RefCell<Vec<ValidationError>>>,
18    pub fail_fast: bool,
19}
20
21impl<'r> Context<'r> {
22    /// Returns true if there are any errors in the context
23    pub fn has_errors(&self) -> bool {
24        !self.errors.borrow().is_empty()
25    }
26
27    /// Returns the current path as a string separated by "."
28    pub fn path(&self) -> String {
29        self.current_path.join(".")
30    }
31
32    pub fn new(fail_fast: bool) -> Context<'r> {
33        Context {
34            fail_fast,
35            ..Default::default()
36        }
37    }
38
39    pub fn get_sub_context(&self) -> Context<'r> {
40        Context {
41            root_schema: self.root_schema,
42            current_schema: self.current_schema.clone(),
43            current_path: self.current_path.clone(),
44            stream_started: self.stream_started,
45            stream_ended: self.stream_ended,
46            errors: Rc::new(RefCell::new(Vec::new())),
47            fail_fast: self.fail_fast,
48        }
49    }
50
51    pub fn with_root_schema(root_schema: &'r RootSchema, fail_fast: bool) -> Context<'r> {
52        Context {
53            root_schema: Some(root_schema),
54            fail_fast,
55            ..Default::default()
56        }
57    }
58
59    fn push_error(&self, error: ValidationError) {
60        self.errors.borrow_mut().push(error);
61    }
62
63    pub fn add_doc_error<V: Into<String>>(&self, error: V) {
64        let path = self.path();
65        self.push_error(ValidationError {
66            path,
67            marker: None,
68            error: error.into(),
69        });
70    }
71
72    /// Adds an error message to the current context, with the current path and with location marker
73    pub fn add_error<V: Into<String>>(&self, marked_yaml: &saphyr::MarkedYaml, error: V) {
74        let path = self.path();
75        self.push_error(ValidationError {
76            path,
77            marker: Some(marked_yaml.span.start),
78            error: error.into(),
79        });
80    }
81
82    /// Appends all the errors to the current context
83    pub fn extend_errors(&self, errors: Vec<ValidationError>) {
84        self.errors.borrow_mut().extend(errors);
85    }
86
87    /// Append a path to the current path
88    pub fn append_path<V: Into<String>>(&self, path: V) -> Context<'r> {
89        let mut new_path = self.current_path.clone();
90        new_path.push(path.into());
91        Context {
92            root_schema: self.root_schema,
93            current_schema: self.current_schema.clone(),
94            current_path: new_path,
95            errors: self.errors.clone(),
96            fail_fast: self.fail_fast,
97            stream_ended: self.stream_ended,
98            stream_started: self.stream_started,
99        }
100    }
101}