fog_pack/validator/
integer.rs

1use super::*;
2use crate::element::*;
3use crate::error::{Error, Result};
4use crate::*;
5use serde::{Deserialize, Serialize};
6
7#[inline]
8fn is_false(v: &bool) -> bool {
9    !v
10}
11
12#[inline]
13fn u64_is_zero(v: &u64) -> bool {
14    *v == 0
15}
16
17#[inline]
18fn int_is_max(v: &Integer) -> bool {
19    v.as_u64().map(|v| v == u64::MAX).unwrap_or(false)
20}
21
22#[inline]
23fn int_is_min(v: &Integer) -> bool {
24    v.as_i64().map(|v| v == i64::MIN).unwrap_or(false)
25}
26
27/// Validator for integer values.
28///
29/// This validator type will only pass integers. Validation passes if:
30///
31/// - The bits set in `bits_clr` are cleared in the integer
32/// - The bits set in `bits_set` are set in the integer
33/// - The integer is less than the maximum in `max`, or equal to it if `ex_max` is not set to true.
34/// - The integer is greater than the minimum in `min`, or equal to it if `ex_min` is not set to true.
35/// - If the `in` list is not empty, the integer must be among the integers in it.
36/// - The integer must not be among the integers in the `nin` list.
37///
38/// # Defaults
39///
40/// Fields that aren't specified for the validator use their defaults instead. The defaults for
41/// each field are:
42///
43/// - comment: ""
44/// - bits_clr: 0
45/// - bits_set: 0
46/// - max: u64::MAX
47/// - min: i64::MIN
48/// - ex_max: false
49/// - ex_min: false
50/// - in_list: empty
51/// - nin_list: empty
52/// - query: false
53/// - bit: false
54/// - ord: false
55///
56#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
57#[serde(deny_unknown_fields, default)]
58pub struct IntValidator {
59    /// An optional comment explaining the validator.
60    #[serde(skip_serializing_if = "String::is_empty")]
61    pub comment: String,
62    /// An unsigned 64-bit integers used as a bit field. Any bits set in it must be cleared in an
63    /// allowed value.
64    #[serde(skip_serializing_if = "u64_is_zero")]
65    pub bits_clr: u64,
66    /// An unsigned 64-bit integers used as a bit field. Any bits set in it must be set in an
67    /// allowed value.
68    #[serde(skip_serializing_if = "u64_is_zero")]
69    pub bits_set: u64,
70    /// The maximum allowed integer value.
71    #[serde(skip_serializing_if = "int_is_max")]
72    pub max: Integer,
73    /// The minimum allowed integer value.
74    #[serde(skip_serializing_if = "int_is_min")]
75    pub min: Integer,
76    /// Changes `max` into an exclusive maximum.
77    #[serde(skip_serializing_if = "is_false")]
78    pub ex_max: bool,
79    /// Changes `min` into an exclusive maximum.
80    #[serde(skip_serializing_if = "is_false")]
81    pub ex_min: bool,
82    /// A vector of specific allowed values, stored under the `in` field. If empty, this vector is not checked against.
83    #[serde(rename = "in", skip_serializing_if = "Vec::is_empty")]
84    pub in_list: Vec<Integer>,
85    /// A vector of specific unallowed values, stored under the `nin` field.
86    #[serde(rename = "nin", skip_serializing_if = "Vec::is_empty")]
87    pub nin_list: Vec<Integer>,
88    /// If true, queries against matching spots may have values in the `in` or `nin` lists.
89    #[serde(skip_serializing_if = "is_false")]
90    pub query: bool,
91    /// If true, queries against matching spots may set the `bits_clr` and `bits_set` values to be
92    /// non-zero.
93    #[serde(skip_serializing_if = "is_false")]
94    pub bit: bool,
95    /// If true, queries against matching spots may set the `max`, `min`, `ex_max`, and `ex_min`
96    /// values to non-defaults.
97    #[serde(skip_serializing_if = "is_false")]
98    pub ord: bool,
99}
100
101impl std::default::Default for IntValidator {
102    fn default() -> Self {
103        Self {
104            comment: String::new(),
105            bits_clr: 0,
106            bits_set: 0,
107            max: Integer::max_value(),
108            min: Integer::min_value(),
109            ex_max: false,
110            ex_min: false,
111            in_list: Vec::new(),
112            nin_list: Vec::new(),
113            query: false,
114            bit: false,
115            ord: false,
116        }
117    }
118}
119
120impl IntValidator {
121    /// Make a new validator with the default configuration.
122    pub fn new() -> Self {
123        Self::default()
124    }
125
126    /// Set a comment for the validator.
127    pub fn comment(mut self, comment: impl Into<String>) -> Self {
128        self.comment = comment.into();
129        self
130    }
131
132    /// Choose which bits must be set.
133    pub fn bits_set(mut self, bits_set: u64) -> Self {
134        self.bits_set = bits_set;
135        self
136    }
137
138    /// Choose which bits must be cleared.
139    pub fn bits_clr(mut self, bits_clr: u64) -> Self {
140        self.bits_clr = bits_clr;
141        self
142    }
143
144    /// Set the maximum allowed value.
145    pub fn max(mut self, max: impl Into<Integer>) -> Self {
146        self.max = max.into();
147        self
148    }
149
150    /// Set the minimum allowed value.
151    pub fn min(mut self, min: impl Into<Integer>) -> Self {
152        self.min = min.into();
153        self
154    }
155
156    /// Set whether or or not `max` is an exclusive maximum.
157    pub fn ex_max(mut self, ex_max: bool) -> Self {
158        self.ex_max = ex_max;
159        self
160    }
161
162    /// Set whether or or not `min` is an exclusive maximum.
163    pub fn ex_min(mut self, ex_min: bool) -> Self {
164        self.ex_min = ex_min;
165        self
166    }
167
168    /// Add a value to the `in` list.
169    pub fn in_add(mut self, add: impl Into<Integer>) -> Self {
170        self.in_list.push(add.into());
171        self
172    }
173
174    /// Add a value to the `nin` list.
175    pub fn nin_add(mut self, add: impl Into<Integer>) -> Self {
176        self.nin_list.push(add.into());
177        self
178    }
179
180    /// Set whether or not queries can use the `in` and `nin` lists.
181    pub fn query(mut self, query: bool) -> Self {
182        self.query = query;
183        self
184    }
185
186    /// Set whether or not queries can use the `bits_clr` and `bits_set` values.
187    pub fn bit(mut self, bit: bool) -> Self {
188        self.bit = bit;
189        self
190    }
191
192    /// Set whether or not queries can use the `max`, `min`, `ex_max`, and `ex_min` values.
193    pub fn ord(mut self, ord: bool) -> Self {
194        self.ord = ord;
195        self
196    }
197
198    /// Build this into a [`Validator`] enum.
199    pub fn build(self) -> Validator {
200        Validator::Int(Box::new(self))
201    }
202
203    pub(crate) fn validate(&self, parser: &mut Parser) -> Result<()> {
204        let elem = parser
205            .next()
206            .ok_or_else(|| Error::FailValidate("Expected a integer".to_string()))??;
207        let int = if let Element::Int(v) = elem {
208            v
209        } else {
210            return Err(Error::FailValidate(format!(
211                "Expected Int, got {}",
212                elem.name()
213            )));
214        };
215        let bits = int.as_bits();
216        if !self.in_list.is_empty() && !self.in_list.iter().any(|v| *v == int) {
217            return Err(Error::FailValidate(
218                "Integer is not on `in` list".to_string(),
219            ));
220        }
221        if self.nin_list.iter().any(|v| *v == int) {
222            return Err(Error::FailValidate("Integer is on `nin` list".to_string()));
223        }
224        if (bits & self.bits_clr) != 0 {
225            return Err(Error::FailValidate(
226                "Integer does not have all required bits cleared".to_string(),
227            ));
228        }
229        if (bits & self.bits_set) != self.bits_set {
230            return Err(Error::FailValidate(
231                "Integer does not have all required bits set".to_string(),
232            ));
233        }
234        match int.cmp(&self.max) {
235            std::cmp::Ordering::Equal if self.ex_max => {
236                return Err(Error::FailValidate(
237                    "Integer greater than maximum allowed".to_string(),
238                ))
239            }
240            std::cmp::Ordering::Greater => {
241                return Err(Error::FailValidate(
242                    "Integer greater than maximum allowed".to_string(),
243                ))
244            }
245            _ => (),
246        }
247        match int.cmp(&self.min) {
248            std::cmp::Ordering::Equal if self.ex_min => {
249                return Err(Error::FailValidate(
250                    "Integer less than minimum allowed".to_string(),
251                ))
252            }
253            std::cmp::Ordering::Less => {
254                return Err(Error::FailValidate(
255                    "Integer less than minimum allowed".to_string(),
256                ))
257            }
258            _ => (),
259        }
260        Ok(())
261    }
262
263    fn query_check_int(&self, other: &Self) -> bool {
264        (self.query || (other.in_list.is_empty() && other.nin_list.is_empty()))
265            && (self.bit || (other.bits_clr == 0 && other.bits_set == 0))
266            && (self.ord
267                || (!other.ex_min
268                    && !other.ex_max
269                    && int_is_max(&other.max)
270                    && int_is_min(&other.min)))
271    }
272
273    pub(crate) fn query_check(&self, other: &Validator) -> bool {
274        match other {
275            Validator::Int(other) => self.query_check_int(other),
276            Validator::Multi(list) => list.iter().all(|other| match other {
277                Validator::Int(other) => self.query_check_int(other),
278                _ => false,
279            }),
280            Validator::Any => true,
281            _ => false,
282        }
283    }
284}