type_rules/rules/
any.rs

1use super::Rule;
2
3/// Rule to constrain an iterable collection (with reference)
4/// to valid that any element of the collection valid the specified rule
5///
6/// # Example
7/// ```
8/// use type_rules::prelude::*;
9///
10/// #[derive(Validator)]
11/// struct VecNotEmptyString(
12///     #[rule(Any(MinLength(10), "At least one element need to be of length >= 10"))]
13///     Vec<String>
14/// );
15/// ```
16pub struct Any<'a, T>(pub T, pub &'a str);
17
18impl<'a, T, U> Rule<U> for Any<'a, T>
19where
20    U: IntoIterator,
21    for<'b> &'b U: IntoIterator<Item = &'b U::Item>,
22    T: Rule<<U as IntoIterator>::Item>,
23{
24    fn check(&self, value: &U) -> Result<(), String> {
25        match value
26            .into_iter()
27            .any(|v: &<U as IntoIterator>::Item| self.0.check(v).is_ok())
28        {
29            true => Ok(()),
30            false => Err(String::from(self.1)),
31        }
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use crate::prelude::*;
38    use claim::{assert_err, assert_ok};
39
40    const ERROR_MESSAGE: &str = "At least one element need to be >= 1";
41    const RULE: Any<MinRange<i32>> = Any(MinRange(1), ERROR_MESSAGE);
42
43    #[test]
44    fn any_ok() {
45        assert_ok!(RULE.check(&vec![0, 1]));
46    }
47    #[test]
48    fn any_err() {
49        assert_err!(RULE.check(&vec![0, 0]));
50    }
51    #[test]
52    fn any_good_error_message() {
53        let res_error_message = RULE.check(&vec![0, 0]).expect_err("Should be an Err");
54        assert_eq!(res_error_message, ERROR_MESSAGE);
55    }
56}