type_rules/rules/
opt.rs

1use super::Rule;
2
3/// Rule to apply another rule to inner value of an [`Option`]
4///
5/// In case of a [`None`] value, it just return `Ok(())`
6///
7/// # Example
8/// ```
9/// use type_rules::prelude::*;
10///
11/// #[derive(Validator)]
12/// struct Parameters {
13///     #[rule(Opt(MinMaxRange(1, 4)))]
14///     optional_parameter: Option<u32>,
15/// }
16///
17/// let param = Parameters { optional_parameter: Some(1) };
18/// assert!(param.check_validity().is_ok());
19///
20/// let param = Parameters { optional_parameter: None };
21/// assert!(param.check_validity().is_ok());
22///
23/// let param = Parameters { optional_parameter: Some(5) };
24/// assert!(param.check_validity().is_err());
25/// ```
26pub struct Opt<T>(pub T);
27
28impl<T, U: Rule<T>> Rule<Option<T>> for Opt<U> {
29    fn check(&self, value: &Option<T>) -> Result<(), String> {
30        match value {
31            Some(val) => self.0.check(val),
32            None => Ok(()),
33        }
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use crate::rules::{MinRange, Opt, Rule};
40    use claim::{assert_err, assert_ok};
41
42    const RULE: Opt<MinRange<i32>> = Opt(MinRange(1));
43
44    #[test]
45    fn opt_ok_with_some() {
46        assert_ok!(RULE.check(&Some(1)));
47    }
48    #[test]
49    fn opt_ok_with_none() {
50        assert_ok!(RULE.check(&None));
51    }
52    #[test]
53    fn opt_err() {
54        assert_err!(RULE.check(&Some(0)));
55    }
56}