Skip to main content

valico/json_dsl/validators/
exactly_one_of.rs

1use serde_json::Value;
2use std::cmp::Ordering;
3
4use super::super::errors;
5
6pub struct ExactlyOneOf {
7    params: Vec<String>,
8}
9
10impl ExactlyOneOf {
11    pub fn new(params: &[&str]) -> ExactlyOneOf {
12        ExactlyOneOf {
13            params: params.iter().map(|s| (*s).to_string()).collect(),
14        }
15    }
16}
17
18impl super::Validator for ExactlyOneOf {
19    fn validate(&self, val: &Value, path: &str) -> super::ValidatorResult {
20        let object = strict_process!(val.as_object(), path, "The value must be an object");
21
22        let mut matched = vec![];
23        for param in self.params.iter() {
24            if object.contains_key(param) {
25                matched.push(param.clone());
26            }
27        }
28
29        match matched.len().cmp(&1) {
30            Ordering::Equal => Ok(()),
31            Ordering::Greater => Err(vec![Box::new(errors::ExactlyOne {
32                path: path.to_string(),
33                detail: Some("Exactly one is allowed at one time".to_string()),
34                params: matched,
35            })]),
36            Ordering::Less => Err(vec![Box::new(errors::ExactlyOne {
37                path: path.to_string(),
38                detail: Some("Exactly one must be present".to_string()),
39                params: self.params.clone(),
40            })]),
41        }
42    }
43}