serde_valid/validation/numeric/
maximum.rs

1use crate::validation::{impl_generic_composited_validation_1args, ValidateCompositedMaximum};
2use crate::MaximumError;
3
4/// Maximum 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, ValidateMaximum};
11/// struct MyType(i32);
12///
13/// impl ValidateMaximum<i32> for MyType {
14///     fn validate_maximum(&self, maximum: i32) -> Result<(), serde_valid::MaximumError> {
15///         self.0.validate_maximum(maximum)
16///     }
17/// }
18///
19/// #[derive(Validate)]
20/// struct TestStruct {
21///     #[validate(maximum = 5)]
22///     val: MyType,
23/// }
24///
25/// let s = TestStruct { val: MyType(6) };
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 ValidateMaximum<T>
41where
42    T: PartialOrd + PartialEq,
43{
44    fn validate_maximum(&self, maximum: T) -> Result<(), MaximumError>;
45}
46
47macro_rules! impl_validate_numeric_maximum {
48    ($type:ty) => {
49        impl ValidateMaximum<$type> for $type {
50            fn validate_maximum(&self, maximum: $type) -> Result<(), MaximumError> {
51                if *self <= maximum {
52                    Ok(())
53                } else {
54                    Err(MaximumError::new(maximum))
55                }
56            }
57        }
58
59        impl_generic_composited_validation_1args!(Maximum, $type);
60    };
61}
62
63impl_validate_numeric_maximum!(i8);
64impl_validate_numeric_maximum!(i16);
65impl_validate_numeric_maximum!(i32);
66impl_validate_numeric_maximum!(i64);
67#[cfg(feature = "i128")]
68impl_validate_numeric_maximum!(i128);
69impl_validate_numeric_maximum!(isize);
70impl_validate_numeric_maximum!(u8);
71impl_validate_numeric_maximum!(u16);
72impl_validate_numeric_maximum!(u32);
73impl_validate_numeric_maximum!(u64);
74#[cfg(feature = "i128")]
75impl_validate_numeric_maximum!(u128);
76impl_validate_numeric_maximum!(usize);
77impl_validate_numeric_maximum!(std::num::NonZeroI8);
78impl_validate_numeric_maximum!(std::num::NonZeroI16);
79impl_validate_numeric_maximum!(std::num::NonZeroI32);
80impl_validate_numeric_maximum!(std::num::NonZeroI64);
81#[cfg(feature = "i128")]
82impl_validate_numeric_maximum!(std::num::NonZeroI128);
83impl_validate_numeric_maximum!(std::num::NonZeroIsize);
84impl_validate_numeric_maximum!(std::num::NonZeroU8);
85impl_validate_numeric_maximum!(std::num::NonZeroU16);
86impl_validate_numeric_maximum!(std::num::NonZeroU32);
87impl_validate_numeric_maximum!(std::num::NonZeroU64);
88#[cfg(feature = "i128")]
89impl_validate_numeric_maximum!(std::num::NonZeroU128);
90impl_validate_numeric_maximum!(std::num::NonZeroUsize);
91impl_validate_numeric_maximum!(f32);
92impl_validate_numeric_maximum!(f64);
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_validate_numeric_maximum_is_true() {
100        // Unspecified generic type:
101        assert!(ValidateMaximum::validate_maximum(&10, 11).is_ok());
102        assert!(ValidateMaximum::validate_maximum(&10, 10).is_ok());
103    }
104
105    #[test]
106    fn test_validate_numeric_maximum_is_false() {
107        assert!(ValidateMaximum::validate_maximum(&10, 9).is_err());
108    }
109
110    #[test]
111    fn test_validate_numeric_maximum_specified_type() {
112        assert!(ValidateMaximum::validate_maximum(&10, 10i8).is_ok());
113        assert!(ValidateMaximum::validate_maximum(&10, 10i16).is_ok());
114        assert!(ValidateMaximum::validate_maximum(&10, 10i32).is_ok());
115        assert!(ValidateMaximum::validate_maximum(&10, 10i64).is_ok());
116        assert!(ValidateMaximum::validate_maximum(&10, 10isize).is_ok());
117
118        assert!(ValidateMaximum::validate_maximum(&10, 10u8).is_ok());
119        assert!(ValidateMaximum::validate_maximum(&10, 10u16).is_ok());
120        assert!(ValidateMaximum::validate_maximum(&10, 10u32).is_ok());
121        assert!(ValidateMaximum::validate_maximum(&10, 10u64).is_ok());
122        assert!(ValidateMaximum::validate_maximum(&10, 10usize).is_ok());
123
124        assert!(ValidateMaximum::validate_maximum(
125            &std::num::NonZeroI8::new(10).unwrap(),
126            std::num::NonZeroI8::new(10).unwrap()
127        )
128        .is_ok());
129        assert!(ValidateMaximum::validate_maximum(
130            &std::num::NonZeroI16::new(10).unwrap(),
131            std::num::NonZeroI16::new(10).unwrap()
132        )
133        .is_ok());
134        assert!(ValidateMaximum::validate_maximum(
135            &std::num::NonZeroI32::new(10).unwrap(),
136            std::num::NonZeroI32::new(10).unwrap()
137        )
138        .is_ok());
139        assert!(ValidateMaximum::validate_maximum(
140            &std::num::NonZeroI64::new(10).unwrap(),
141            std::num::NonZeroI64::new(10).unwrap()
142        )
143        .is_ok());
144        assert!(ValidateMaximum::validate_maximum(
145            &std::num::NonZeroIsize::new(10).unwrap(),
146            std::num::NonZeroIsize::new(10).unwrap()
147        )
148        .is_ok());
149
150        assert!(ValidateMaximum::validate_maximum(
151            &std::num::NonZeroU8::new(10).unwrap(),
152            std::num::NonZeroU8::new(10).unwrap()
153        )
154        .is_ok());
155        assert!(ValidateMaximum::validate_maximum(
156            &std::num::NonZeroU16::new(10).unwrap(),
157            std::num::NonZeroU16::new(10).unwrap()
158        )
159        .is_ok());
160        assert!(ValidateMaximum::validate_maximum(
161            &std::num::NonZeroU32::new(10).unwrap(),
162            std::num::NonZeroU32::new(10).unwrap()
163        )
164        .is_ok());
165        assert!(ValidateMaximum::validate_maximum(
166            &std::num::NonZeroU64::new(10).unwrap(),
167            std::num::NonZeroU64::new(10).unwrap()
168        )
169        .is_ok());
170        assert!(ValidateMaximum::validate_maximum(
171            &std::num::NonZeroUsize::new(10).unwrap(),
172            std::num::NonZeroUsize::new(10).unwrap()
173        )
174        .is_ok());
175
176        assert!(ValidateMaximum::validate_maximum(&10.0, 10.0f32).is_ok());
177        assert!(ValidateMaximum::validate_maximum(&10.0, 10.0f64).is_ok());
178    }
179
180    #[test]
181    fn test_validate_numeric_maximum_128() {
182        assert!(ValidateMaximum::validate_maximum(&10, 10i128).is_ok());
183        assert!(ValidateMaximum::validate_maximum(&10, 10u128).is_ok());
184        assert!(ValidateMaximum::validate_maximum(
185            &std::num::NonZeroI128::new(10).unwrap(),
186            std::num::NonZeroI128::new(10).unwrap()
187        )
188        .is_ok());
189        assert!(ValidateMaximum::validate_maximum(
190            &std::num::NonZeroU128::new(10).unwrap(),
191            std::num::NonZeroU128::new(10).unwrap()
192        )
193        .is_ok());
194    }
195}