type_rules/rules/
or.rs

1use super::Rule;
2
3/// Rule to apply an Or condition on two rules.
4///
5/// In case of error on both rules, the first one is returned.
6///
7/// # Example
8/// ```
9/// use type_rules::prelude::*;
10///
11/// #[derive(Validator)]
12/// struct NotZeroInteger(
13///     #[rule(Or(MaxRange(-1), MinRange(1)))]
14///     i32
15/// );
16/// ```
17pub struct Or<T, U>(pub T, pub U);
18
19impl<T, U, F> Rule<F> for Or<T, U>
20where
21    T: Rule<F>,
22    U: Rule<F>,
23{
24    fn check(&self, value: &F) -> Result<(), String> {
25        let first_res = self.0.check(value);
26        let second_res = self.1.check(value);
27
28        if first_res.is_ok() || second_res.is_ok() {
29            Ok(())
30        } else {
31            first_res
32        }
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use crate::prelude::*;
39    use claim::assert_ok;
40
41    const RULE: Or<MaxRange<i32>, MinRange<i32>> = Or(MaxRange(-1), MinRange(1));
42
43    #[test]
44    fn or_0_ok() {
45        assert_ok!(RULE.check(&-1));
46    }
47
48    #[test]
49    fn or_1_ok() {
50        assert_ok!(RULE.check(&1));
51    }
52
53    #[test]
54    fn or_err() {
55        let res_error_message = RULE.check(&0).expect_err("Should be an Err");
56
57        assert_eq!(res_error_message, "Value is too high")
58    }
59}