Skip to content

Commit 4b2ee54

Browse files
authored
Merge pull request #63 from yassun7010/add_duration_utils
feat: add duration validation.
2 parents 43320a9 + 0a9301a commit 4b2ee54

File tree

7 files changed

+335
-10
lines changed

7 files changed

+335
-10
lines changed

serde_valid/README.md

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ assert!(s.validate().is_ok());
4545

4646
Serde Valid support standard validation based JSON Schema.
4747

48-
| Type | Serde Valid(validate derive) | Serde Valid(validate trait) | Json Schema |
48+
| Type | Serde Valid (validate derive) | Serde Valid (validate trait) | JSON Schema |
4949
| :-----: | :----------------------------------- | :--------------------------- | :-------------------------------------------------------------------------------------------- |
5050
| String | `#[validate(max_length = 5)]` | [`ValidateMaxLength`] | [maxLength](https://json-schema.org/understanding-json-schema/reference/string#length) |
5151
| String | `#[validate(min_length = 5)]` | [`ValidateMinLength`] | [minLength](https://json-schema.org/understanding-json-schema/reference/string#length) |
@@ -62,6 +62,15 @@ Serde Valid support standard validation based JSON Schema.
6262
| Array | `#[validate(unique_items)]` | [`ValidateUniqueItems`] | [uniqueItems](https://json-schema.org/understanding-json-schema/reference/array#uniqueItems) |
6363
| Generic | `#[validate(enumerate(5, 10, 15))]` | [`ValidateEnumerate`] | [enum](https://json-schema.org/understanding-json-schema/reference/enum) |
6464

65+
In addition, [serde_valid::utils][module@crate::utils] provides a type of validation not described in the JSON schema specification.
66+
67+
| Type | Serde Valid (validate derive) | Serde Valid (validation function) |
68+
| :-------------------------------: | :-------------------------------------------------------- | :----------------------------------------------------------------------- |
69+
| [Duration][`std::time::Duration`] | `#[validate(custom(duration_maximum(SECOND)))]` | [duration_maximum][`crate::utils::duration_maximum`] |
70+
| [Duration][`std::time::Duration`] | `#[validate(custom(duration_minimum(ZERO)))]` | [duration_minimum][`crate::utils::duration_minimum`] |
71+
| [Duration][`std::time::Duration`] | `#[validate(custom(duration_exclusive_maximum(SECOND)))]` | [duration_exclusive_maximum][`crate::utils::duration_exclusive_maximum`] |
72+
| [Duration][`std::time::Duration`] | `#[validate(custom(duration_exclusive_minimum(ZERO)))]` | [duration_exclusive_minimum][`crate::utils::duration_exclusive_minimum`] |
73+
6574
## Complete Constructor (Deserialization)
6675

6776
Serde Valid support complete constructor method using by
@@ -129,13 +138,13 @@ use serde_valid::Validate;
129138

130139
#[inline]
131140
fn min_error_message(_params: &serde_valid::MinItemsError) -> String {
132-
"this is min custom message_fn.".to_string()
141+
"this is custom message_fn.".to_string()
133142
}
134143

135144
#[derive(Validate)]
136145
struct Data {
137146
#[validate(min_items = 4, message_fn(min_error_message))]
138-
#[validate(max_items = 2, message = "this is max custom message.")]
147+
#[validate(max_items = 2, message = "this is custom message.")]
139148
val: Vec<i32>,
140149
}
141150

@@ -148,8 +157,8 @@ assert_eq!(
148157
"properties": {
149158
"val": {
150159
"errors": [
151-
"this is min custom message_fn.",
152-
"this is max custom message."
160+
"this is custom message_fn.",
161+
"this is custom message."
153162
]
154163
}
155164
}
@@ -228,6 +237,29 @@ let s = Data { val: 1 };
228237
assert!(s.validate().is_ok());
229238
```
230239

240+
Custom validation is suitable for handling convenience validations not defined in JSON Schema.
241+
`serde_valid::utils::*` provides convenience functions for specific types.
242+
243+
```rust
244+
use serde_json::json;
245+
use serde_valid::Validate;
246+
use serde_valid::utils::{duration_maximum, duration_minimum};
247+
248+
249+
#[derive(Validate)]
250+
struct Data {
251+
#[validate(custom(duration_maximum(std::time::Duration::from_micros(5))))]
252+
#[validate(custom(duration_minimum(std::time::Duration::from_micros(0))))]
253+
val1: std::time::Duration,
254+
}
255+
256+
let s = Data {
257+
val1: std::time::Duration::from_micros(1),
258+
};
259+
260+
assert!(s.validate().is_ok());
261+
```
262+
231263
## Multi Fields Validation
232264
### Custom Validation
233265
Now, you can use `#[validate(custom)]` for multi fields validation.

serde_valid/src/lib.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
//!
4646
//! Serde Valid support standard validation based JSON Schema.
4747
//!
48-
//! | Type | Serde Valid(validate derive) | Serde Valid(validate trait) | Json Schema |
48+
//! | Type | Serde Valid (validate derive) | Serde Valid (validate trait) | JSON Schema |
4949
//! | :-----: | :----------------------------------- | :--------------------------- | :-------------------------------------------------------------------------------------------- |
5050
//! | String | `#[validate(max_length = 5)]` | [`ValidateMaxLength`] | [maxLength](https://json-schema.org/understanding-json-schema/reference/string#length) |
5151
//! | String | `#[validate(min_length = 5)]` | [`ValidateMinLength`] | [minLength](https://json-schema.org/understanding-json-schema/reference/string#length) |
@@ -62,6 +62,15 @@
6262
//! | Array | `#[validate(unique_items)]` | [`ValidateUniqueItems`] | [uniqueItems](https://json-schema.org/understanding-json-schema/reference/array#uniqueItems) |
6363
//! | Generic | `#[validate(enumerate(5, 10, 15))]` | [`ValidateEnumerate`] | [enum](https://json-schema.org/understanding-json-schema/reference/enum) |
6464
//!
65+
//! In addition, [serde_valid::utils][module@crate::utils] provides a type of validation not described in the JSON schema specification.
66+
//!
67+
//! | Type | Serde Valid (validate derive) | Serde Valid (validation function) |
68+
//! | :-------------------------------: | :-------------------------------------------------------- | :----------------------------------------------------------------------- |
69+
//! | [Duration][`std::time::Duration`] | `#[validate(custom(duration_maximum(SECOND)))]` | [duration_maximum][`crate::utils::duration_maximum`] |
70+
//! | [Duration][`std::time::Duration`] | `#[validate(custom(duration_minimum(ZERO)))]` | [duration_minimum][`crate::utils::duration_minimum`] |
71+
//! | [Duration][`std::time::Duration`] | `#[validate(custom(duration_exclusive_maximum(SECOND)))]` | [duration_exclusive_maximum][`crate::utils::duration_exclusive_maximum`] |
72+
//! | [Duration][`std::time::Duration`] | `#[validate(custom(duration_exclusive_minimum(ZERO)))]` | [duration_exclusive_minimum][`crate::utils::duration_exclusive_minimum`] |
73+
//!
6574
//! ## Complete Constructor (Deserialization)
6675
//!
6776
//! Serde Valid support complete constructor method using by
@@ -129,13 +138,13 @@
129138
//!
130139
//! #[inline]
131140
//! fn min_error_message(_params: &serde_valid::MinItemsError) -> String {
132-
//! "this is min custom message_fn.".to_string()
141+
//! "this is custom message_fn.".to_string()
133142
//! }
134143
//!
135144
//! #[derive(Validate)]
136145
//! struct Data {
137146
//! #[validate(min_items = 4, message_fn(min_error_message))]
138-
//! #[validate(max_items = 2, message = "this is max custom message.")]
147+
//! #[validate(max_items = 2, message = "this is custom message.")]
139148
//! val: Vec<i32>,
140149
//! }
141150
//!
@@ -148,8 +157,8 @@
148157
//! "properties": {
149158
//! "val": {
150159
//! "errors": [
151-
//! "this is min custom message_fn.",
152-
//! "this is max custom message."
160+
//! "this is custom message_fn.",
161+
//! "this is custom message."
153162
//! ]
154163
//! }
155164
//! }
@@ -238,6 +247,29 @@
238247
//! assert!(s.validate().is_ok());
239248
//! ```
240249
//!
250+
//! Custom validation is suitable for handling convenience validations not defined in JSON Schema.
251+
//! `serde_valid::utils::*` provides convenience functions for specific types.
252+
//!
253+
//! ```rust
254+
//! use serde_json::json;
255+
//! use serde_valid::Validate;
256+
//! use serde_valid::utils::{duration_maximum, duration_minimum};
257+
//!
258+
//!
259+
//! #[derive(Validate)]
260+
//! struct Data {
261+
//! #[validate(custom(duration_maximum(std::time::Duration::from_micros(5))))]
262+
//! #[validate(custom(duration_minimum(std::time::Duration::from_micros(0))))]
263+
//! val1: std::time::Duration,
264+
//! }
265+
//!
266+
//! let s = Data {
267+
//! val1: std::time::Duration::from_micros(1),
268+
//! };
269+
//!
270+
//! assert!(s.validate().is_ok());
271+
//! ```
272+
//!
241273
//! ## Multi Fields Validation
242274
//! ### Custom Validation
243275
//! Now, you can use `#[validate(custom)]` for multi fields validation.
@@ -591,6 +623,7 @@ pub use error::{
591623
MaxLengthError, MaxPropertiesError, MaximumError, MinItemsError, MinLengthError,
592624
MinPropertiesError, MinimumError, MultipleOfError, PatternError, UniqueItemsError,
593625
};
626+
pub mod utils;
594627
pub use validation::{
595628
ValidateEnumerate, ValidateExclusiveMaximum, ValidateExclusiveMinimum, ValidateMaxItems,
596629
ValidateMaxLength, ValidateMaxProperties, ValidateMaximum, ValidateMinItems, ValidateMinLength,

serde_valid/src/utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mod duration;
2+
3+
pub use duration::duration_exclusive_maximum;
4+
pub use duration::duration_exclusive_minimum;
5+
pub use duration::duration_maximum;
6+
pub use duration::duration_minimum;

serde_valid/src/utils/duration.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
use std::time::Duration;
2+
3+
/// Validate that the duration is less than or equal to the maximum.
4+
///
5+
/// # Example
6+
///
7+
/// ```rust
8+
/// use std::time::Duration;
9+
///
10+
/// use serde_valid::utils::duration_maximum;
11+
/// use serde_valid::Validate;
12+
///
13+
/// #[derive(Validate)]
14+
/// struct TestStruct {
15+
/// #[validate(custom(duration_maximum(Duration::from_micros(5))))]
16+
/// val: Duration,
17+
/// }
18+
///
19+
/// let s = TestStruct {
20+
/// val: Duration::from_micros(5),
21+
/// };
22+
///
23+
/// assert!(s.validate().is_ok());
24+
/// ```
25+
#[allow(dead_code)]
26+
pub fn duration_maximum(
27+
maximum: Duration,
28+
) -> impl FnOnce(&Duration) -> Result<(), crate::validation::Error> {
29+
move |val: &Duration| {
30+
if *val <= maximum {
31+
Ok(())
32+
} else {
33+
Err(crate::validation::Error::Custom(format!(
34+
"Duration {val:?} is greater than maximum {maximum:?}.",
35+
)))
36+
}
37+
}
38+
}
39+
40+
/// Validate that the duration is greater than or equal to the minimum.
41+
///
42+
/// # Example
43+
///
44+
/// ```rust
45+
/// use std::time::Duration;
46+
///
47+
/// use serde_valid::utils::duration_minimum;
48+
/// use serde_valid::Validate;
49+
///
50+
/// #[derive(Validate)]
51+
/// struct TestStruct {
52+
/// #[validate(custom(duration_minimum(Duration::from_micros(5))))]
53+
/// val: Duration,
54+
/// }
55+
///
56+
/// let s = TestStruct {
57+
/// val: Duration::from_secs(5),
58+
/// };
59+
///
60+
/// assert!(s.validate().is_ok());
61+
/// ```
62+
#[allow(dead_code)]
63+
pub fn duration_minimum(
64+
minimum: Duration,
65+
) -> impl FnOnce(&Duration) -> Result<(), crate::validation::Error> {
66+
move |val: &Duration| {
67+
if *val >= minimum {
68+
Ok(())
69+
} else {
70+
Err(crate::validation::Error::Custom(format!(
71+
"Duration {val:?} is less than minimum {minimum:?}.",
72+
)))
73+
}
74+
}
75+
}
76+
77+
/// Validate that the duration is less than the exclusive maximum.
78+
///
79+
/// # Example
80+
///
81+
/// ```rust
82+
/// use std::time::Duration;
83+
///
84+
/// use serde_valid::utils::duration_exclusive_maximum;
85+
/// use serde_valid::Validate;
86+
///
87+
/// #[derive(Validate)]
88+
/// struct TestStruct {
89+
/// #[validate(custom(duration_exclusive_maximum(Duration::from_micros(5))))]
90+
/// val: Duration,
91+
/// }
92+
///
93+
/// let s = TestStruct {
94+
/// val: Duration::from_micros(4),
95+
/// };
96+
///
97+
/// assert!(s.validate().is_ok());
98+
/// ```
99+
#[allow(dead_code)]
100+
pub fn duration_exclusive_maximum(
101+
maximum: Duration,
102+
) -> impl FnOnce(&Duration) -> Result<(), crate::validation::Error> {
103+
move |val: &Duration| {
104+
if *val < maximum {
105+
Ok(())
106+
} else {
107+
Err(crate::validation::Error::Custom(format!(
108+
"Duration {val:?} is greater than or equal to exclusive maximum {maximum:?}.",
109+
)))
110+
}
111+
}
112+
}
113+
114+
/// Validate that the duration is greater than the exclusive minimum.
115+
///
116+
/// # Example
117+
///
118+
/// ```rust
119+
/// use std::time::Duration;
120+
///
121+
/// use serde_valid::utils::duration_exclusive_minimum;
122+
/// use serde_valid::Validate;
123+
///
124+
/// #[derive(Validate)]
125+
/// struct TestStruct {
126+
/// #[validate(custom(duration_exclusive_minimum(Duration::from_micros(5))))]
127+
/// val: Duration,
128+
/// }
129+
///
130+
/// let s = TestStruct {
131+
/// val: Duration::from_micros(6),
132+
/// };
133+
///
134+
/// assert!(s.validate().is_ok());
135+
/// ```
136+
#[allow(dead_code)]
137+
pub fn duration_exclusive_minimum(
138+
minimum: Duration,
139+
) -> impl FnOnce(&Duration) -> Result<(), crate::validation::Error> {
140+
move |val: &Duration| {
141+
if *val > minimum {
142+
Ok(())
143+
} else {
144+
Err(crate::validation::Error::Custom(format!(
145+
"Duration {val:?} is less than or equal to exclusive minimum {minimum:?}.",
146+
)))
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)