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}