serde_valid/validation/numeric/
minimum.rs

1use crate::validation::{impl_generic_composited_validation_1args, ValidateCompositedMinimum};
2use crate::MinimumError;
3
4/// Minimum validation of the number.
5///
6/// See <https://json-schema.org/understanding-json-schema/reference/numeric.html#range>
7///
8/// ```rust
9/// use serde_json::json;
10/// use serde_valid::{Validate, ValidateMinimum};
11/// struct MyType(i32);
12///
13/// impl ValidateMinimum<i32> for MyType {
14///     fn validate_minimum(&self, minimum: i32) -> Result<(), serde_valid::MinimumError> {
15///         self.0.validate_minimum(minimum)
16///     }
17/// }
18///
19/// #[derive(Validate)]
20/// struct TestStruct {
21///     #[validate(minimum = 5)]
22///     val: MyType,
23/// }
24///
25/// let s = TestStruct { val: MyType(3) };
26///
27/// assert_eq!(
28///     s.validate().unwrap_err().to_string(),
29///     json!({
30///         "errors": [],
31///         "properties": {
32///             "val": {
33///                 "errors": ["The number must be `>= 5`."]
34///             }
35///         }
36///     })
37///     .to_string()
38/// );
39/// ```
40pub trait ValidateMinimum<T>
41where
42    T: PartialOrd + PartialEq,
43{
44    fn validate_minimum(&self, minimum: T) -> Result<(), MinimumError>;
45}
46
47macro_rules! impl_validate_numeric_minimum {
48    ($type:ty) => {
49        impl ValidateMinimum<$type> for $type {
50            fn validate_minimum(&self, minimum: $type) -> Result<(), MinimumError> {
51                if *self >= minimum {
52                    Ok(())
53                } else {
54                    Err(MinimumError::new(minimum))
55                }
56            }
57        }
58
59        impl_generic_composited_validation_1args!(Minimum, $type);
60    };
61}
62
63impl_validate_numeric_minimum!(i8);
64impl_validate_numeric_minimum!(i16);
65impl_validate_numeric_minimum!(i32);
66impl_validate_numeric_minimum!(i64);
67#[cfg(feature = "i128")]
68impl_validate_numeric_minimum!(i128);
69impl_validate_numeric_minimum!(isize);
70impl_validate_numeric_minimum!(u8);
71impl_validate_numeric_minimum!(u16);
72impl_validate_numeric_minimum!(u32);
73impl_validate_numeric_minimum!(u64);
74#[cfg(feature = "i128")]
75impl_validate_numeric_minimum!(u128);
76impl_validate_numeric_minimum!(usize);
77impl_validate_numeric_minimum!(std::num::NonZeroI8);
78impl_validate_numeric_minimum!(std::num::NonZeroI16);
79impl_validate_numeric_minimum!(std::num::NonZeroI32);
80impl_validate_numeric_minimum!(std::num::NonZeroI64);
81#[cfg(feature = "i128")]
82impl_validate_numeric_minimum!(std::num::NonZeroI128);
83impl_validate_numeric_minimum!(std::num::NonZeroIsize);
84impl_validate_numeric_minimum!(std::num::NonZeroU8);
85impl_validate_numeric_minimum!(std::num::NonZeroU16);
86impl_validate_numeric_minimum!(std::num::NonZeroU32);
87impl_validate_numeric_minimum!(std::num::NonZeroU64);
88#[cfg(feature = "i128")]
89impl_validate_numeric_minimum!(std::num::NonZeroU128);
90impl_validate_numeric_minimum!(std::num::NonZeroUsize);
91impl_validate_numeric_minimum!(f32);
92impl_validate_numeric_minimum!(f64);
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_validate_numeric_minimum_is_true() {
100        assert!(ValidateMinimum::validate_minimum(&10, 9).is_ok());
101        assert!(ValidateMinimum::validate_minimum(&10, 10).is_ok());
102    }
103
104    #[test]
105    fn test_validate_numeric_minimum_is_false() {
106        assert!(ValidateMinimum::validate_minimum(&10, 11).is_err());
107    }
108
109    #[test]
110    fn test_validate_numeric_minimum_specified_type() {
111        assert!(ValidateMinimum::validate_minimum(&10, 10i8).is_ok());
112        assert!(ValidateMinimum::validate_minimum(&10, 10i16).is_ok());
113        assert!(ValidateMinimum::validate_minimum(&10, 10i32).is_ok());
114        assert!(ValidateMinimum::validate_minimum(&10, 10i64).is_ok());
115        assert!(ValidateMinimum::validate_minimum(&10, 10isize).is_ok());
116
117        assert!(ValidateMinimum::validate_minimum(&10, 10u8).is_ok());
118        assert!(ValidateMinimum::validate_minimum(&10, 10u16).is_ok());
119        assert!(ValidateMinimum::validate_minimum(&10, 10u32).is_ok());
120        assert!(ValidateMinimum::validate_minimum(&10, 10u64).is_ok());
121        assert!(ValidateMinimum::validate_minimum(&10, 10usize).is_ok());
122
123        assert!(ValidateMinimum::validate_minimum(
124            &std::num::NonZeroI8::new(10).unwrap(),
125            std::num::NonZeroI8::new(10).unwrap()
126        )
127        .is_ok());
128        assert!(ValidateMinimum::validate_minimum(
129            &std::num::NonZeroI16::new(10).unwrap(),
130            std::num::NonZeroI16::new(10).unwrap()
131        )
132        .is_ok());
133        assert!(ValidateMinimum::validate_minimum(
134            &std::num::NonZeroI32::new(10).unwrap(),
135            std::num::NonZeroI32::new(10).unwrap()
136        )
137        .is_ok());
138        assert!(ValidateMinimum::validate_minimum(
139            &std::num::NonZeroI64::new(10).unwrap(),
140            std::num::NonZeroI64::new(10).unwrap()
141        )
142        .is_ok());
143        assert!(ValidateMinimum::validate_minimum(
144            &std::num::NonZeroIsize::new(10).unwrap(),
145            std::num::NonZeroIsize::new(10).unwrap()
146        )
147        .is_ok());
148
149        assert!(ValidateMinimum::validate_minimum(
150            &std::num::NonZeroU8::new(10).unwrap(),
151            std::num::NonZeroU8::new(10).unwrap()
152        )
153        .is_ok());
154        assert!(ValidateMinimum::validate_minimum(
155            &std::num::NonZeroU16::new(10).unwrap(),
156            std::num::NonZeroU16::new(10).unwrap()
157        )
158        .is_ok());
159        assert!(ValidateMinimum::validate_minimum(
160            &std::num::NonZeroU32::new(10).unwrap(),
161            std::num::NonZeroU32::new(10).unwrap()
162        )
163        .is_ok());
164        assert!(ValidateMinimum::validate_minimum(
165            &std::num::NonZeroU64::new(10).unwrap(),
166            std::num::NonZeroU64::new(10).unwrap()
167        )
168        .is_ok());
169        assert!(ValidateMinimum::validate_minimum(
170            &std::num::NonZeroUsize::new(10).unwrap(),
171            std::num::NonZeroUsize::new(10).unwrap()
172        )
173        .is_ok());
174
175        assert!(ValidateMinimum::validate_minimum(&10.0, 10.0f32).is_ok());
176        assert!(ValidateMinimum::validate_minimum(&10.0, 10.0f64).is_ok());
177    }
178
179    #[test]
180    #[cfg(feature = "i128")]
181    fn test_validate_numeric_minimum_128() {
182        assert!(ValidateMinimum::validate_minimum(&10, 10i128).is_ok());
183        assert!(ValidateMinimum::validate_minimum(&10, 10u128).is_ok());
184        assert!(ValidateMinimum::validate_minimum(
185            &std::num::NonZeroI128::new(10).unwrap(),
186            std::num::NonZeroI128::new(10).unwrap()
187        )
188        .is_ok());
189        assert!(ValidateMinimum::validate_minimum(
190            &std::num::NonZeroU128::new(10).unwrap(),
191            std::num::NonZeroU128::new(10).unwrap()
192        )
193        .is_ok());
194    }
195}