serde_valid/validation/array/
unique_items.rs

1use crate::traits::IsUnique;
2
3/// Uniqueness validation of the array items.
4///
5/// See <https://json-schema.org/understanding-json-schema/reference/array.html#unique_items>
6///
7/// ```rust
8/// use serde_json::json;
9/// use serde_valid::{Validate, ValidateUniqueItems};
10///
11/// struct MyType(Vec<i32>);
12///
13/// impl ValidateUniqueItems for MyType {
14///     fn validate_unique_items(&self) -> Result<(), serde_valid::UniqueItemsError> {
15///         self.0.validate_unique_items()
16///     }
17/// }
18///
19/// #[derive(Validate)]
20/// struct TestStruct {
21///     #[validate(unique_items)]
22///     val: MyType,
23/// }
24///
25/// let s = TestStruct {
26///     val: MyType(vec![1, 2, 1]),
27/// };
28///
29/// assert_eq!(
30///     s.validate().unwrap_err().to_string(),
31///     json!({
32///         "errors": [],
33///         "properties": {
34///             "val": {
35///                 "errors": ["The items must be unique."]
36///             }
37///         }
38///     })
39///     .to_string()
40/// );
41/// ```
42pub trait ValidateUniqueItems {
43    fn validate_unique_items(&self) -> Result<(), crate::UniqueItemsError>;
44}
45
46impl<T> ValidateUniqueItems for Vec<T>
47where
48    T: std::cmp::Eq + std::hash::Hash + std::fmt::Debug,
49{
50    fn validate_unique_items(&self) -> Result<(), crate::UniqueItemsError> {
51        if self.is_unique() {
52            Ok(())
53        } else {
54            Err(crate::UniqueItemsError {})
55        }
56    }
57}
58
59impl<T, const N: usize> ValidateUniqueItems for [T; N]
60where
61    T: std::cmp::Eq + std::hash::Hash + std::fmt::Debug,
62{
63    fn validate_unique_items(&self) -> Result<(), crate::UniqueItemsError> {
64        if self.is_unique() {
65            Ok(())
66        } else {
67            Err(crate::UniqueItemsError {})
68        }
69    }
70}
71
72impl<T> ValidateUniqueItems for Option<T>
73where
74    T: ValidateUniqueItems,
75{
76    fn validate_unique_items(&self) -> Result<(), crate::UniqueItemsError> {
77        match self {
78            Some(value) => value.validate_unique_items(),
79            None => Ok(()),
80        }
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn test_validate_array_unique_items_array_type_is_true() {
90        assert!(ValidateUniqueItems::validate_unique_items(&[1, 2, 3, 4]).is_ok());
91    }
92
93    #[test]
94    fn test_validate_array_unique_items_vec_type_is_true() {
95        assert!(ValidateUniqueItems::validate_unique_items(&vec![1, 2, 3, 4]).is_ok());
96    }
97
98    #[test]
99    fn test_validate_array_unique_items_is_false() {
100        assert!(ValidateUniqueItems::validate_unique_items(&[1, 2, 3, 3]).is_err());
101    }
102}