fog_pack/validator/
bool.rs

1use super::*;
2use crate::element::*;
3use crate::error::{Error, Result};
4use serde::{Deserialize, Serialize};
5
6#[inline]
7fn is_false(v: &bool) -> bool {
8    !v
9}
10
11/// Validator for boolean values.
12///
13/// This validator type will only pass booleans. Validation only passes if the value also
14/// meets the `in`/`nin` requirements.
15///
16/// # Defaults
17///
18/// Fields that aren't specified for the validator use their defaults instead. The defaults for
19/// each field are:
20/// - comment: ""
21/// - in_list: empty
22/// - nin_list: empty
23/// - query: false
24///
25#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
26#[serde(deny_unknown_fields, default)]
27pub struct BoolValidator {
28    /// An optional comment explaining the validator.
29    #[serde(skip_serializing_if = "String::is_empty")]
30    pub comment: String,
31    /// A vector of specific allowed values, stored under the `in` field. If empty, this vector is not checked against.
32    #[serde(rename = "in", skip_serializing_if = "Vec::is_empty")]
33    pub in_list: Vec<bool>,
34    /// A vector of specific unallowed values, stored under the `nin` field.
35    #[serde(rename = "nin", skip_serializing_if = "Vec::is_empty")]
36    pub nin_list: Vec<bool>,
37    /// If true, queries against matching spots may have values in the `in` or `nin` lists.
38    #[serde(skip_serializing_if = "is_false")]
39    pub query: bool,
40}
41
42impl BoolValidator {
43    /// Make a new validator with the default configuration.
44    pub fn new() -> Self {
45        Self::default()
46    }
47
48    /// Set a comment for the validator.
49    pub fn comment(mut self, comment: impl Into<String>) -> Self {
50        self.comment = comment.into();
51        self
52    }
53
54    /// Add a value to the `in` list.
55    pub fn in_add(mut self, add: bool) -> Self {
56        self.in_list.push(add);
57        self
58    }
59
60    /// Add a value to the `nin` list.
61    pub fn nin_add(mut self, add: bool) -> Self {
62        self.nin_list.push(add);
63        self
64    }
65
66    /// Set whether or not queries can use the `in` and `nin` lists.
67    pub fn query(mut self, query: bool) -> Self {
68        self.query = query;
69        self
70    }
71
72    /// Build this into a [`Validator`] enum.
73    pub fn build(self) -> Validator {
74        Validator::Bool(Box::new(self))
75    }
76
77    pub(crate) fn validate(&self, parser: &mut Parser) -> Result<()> {
78        let elem = parser
79            .next()
80            .ok_or_else(|| Error::FailValidate("Expected a boolean".to_string()))??;
81        let elem = if let Element::Bool(v) = elem {
82            v
83        } else {
84            return Err(Error::FailValidate(format!(
85                "Expected Bool, got {}",
86                elem.name()
87            )));
88        };
89        if !self.in_list.is_empty() && !self.in_list.iter().any(|v| *v == elem) {
90            return Err(Error::FailValidate(
91                "Boolean is not on `in` list".to_string(),
92            ));
93        }
94        if self.nin_list.iter().any(|v| *v == elem) {
95            return Err(Error::FailValidate("Boolean is on `nin` list".to_string()));
96        }
97        Ok(())
98    }
99
100    fn query_check_bool(&self, other: &Self) -> bool {
101        self.query || (other.in_list.is_empty() && other.nin_list.is_empty())
102    }
103
104    pub(crate) fn query_check(&self, other: &Validator) -> bool {
105        match other {
106            Validator::Bool(other) => self.query_check_bool(other),
107            Validator::Multi(list) => list.iter().all(|other| match other {
108                Validator::Bool(other) => self.query_check_bool(other),
109                _ => false,
110            }),
111            Validator::Any => true,
112            _ => false,
113        }
114    }
115}