valico/json_dsl/validators/
exactly_one_of.rs1use 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}