serde_valid/validation/string/
max_length.rs

1use crate::{traits::Length, MaxLengthError};
2
3/// Max length validation of the string.
4///
5/// See <https://json-schema.org/understanding-json-schema/reference/string.html#length>
6///
7/// ```rust
8/// use serde_json::json;
9/// use serde_valid::{Validate, ValidateMaxLength};
10///
11/// struct MyType(String);
12///
13/// impl ValidateMaxLength for MyType {
14///     fn validate_max_length(
15///         &self,
16///         max_length: usize,
17///     ) -> Result<(), serde_valid::MaxLengthError> {
18///         self.0.validate_max_length(max_length)
19///     }
20/// }
21///
22/// #[derive(Validate)]
23/// struct TestStruct {
24///     #[validate(max_length = 5)]
25///     val: MyType,
26/// }
27///
28/// let s = TestStruct {
29///     val: MyType(String::from("abcdef")),
30/// };
31///
32/// assert_eq!(
33///     s.validate().unwrap_err().to_string(),
34///     json!({
35///         "errors": [],
36///         "properties": {
37///             "val": {
38///                 "errors": ["The length of the value must be `<= 5`."]
39///             }
40///         }
41///     })
42///     .to_string()
43/// );
44/// ```
45pub trait ValidateMaxLength {
46    fn validate_max_length(&self, max_length: usize) -> Result<(), MaxLengthError>;
47}
48
49impl<T> ValidateMaxLength for T
50where
51    T: Length + ?Sized,
52{
53    fn validate_max_length(&self, max_length: usize) -> Result<(), MaxLengthError> {
54        if max_length >= self.length() {
55            Ok(())
56        } else {
57            Err(MaxLengthError::new(max_length))
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use std::borrow::Cow;
66    use std::ffi::{OsStr, OsString};
67    use std::path::{Path, PathBuf};
68
69    #[test]
70    fn test_validate_string_max_length_ascii_is_true() {
71        assert!(ValidateMaxLength::validate_max_length("abcde", 5).is_ok());
72        assert!(ValidateMaxLength::validate_max_length("abcde", 6).is_ok());
73    }
74
75    #[test]
76    fn test_validate_string_max_length_unicode_is_true() {
77        assert!(ValidateMaxLength::validate_max_length("a̐éö̲", 3).is_ok());
78    }
79
80    #[test]
81    fn test_validate_string_max_length_japanese_is_true() {
82        assert!(ValidateMaxLength::validate_max_length("あ堯", 2).is_ok());
83    }
84
85    #[test]
86    fn test_validate_string_max_length_emoji_is_true() {
87        assert!(ValidateMaxLength::validate_max_length("😍👺🙋🏽👨‍🎤👨‍👩‍👧‍👦", 5).is_ok());
88    }
89
90    #[test]
91    fn test_validate_string_max_length_string_type() {
92        assert!(ValidateMaxLength::validate_max_length(&String::from("abcde"), 5).is_ok());
93    }
94
95    #[test]
96    fn test_validate_string_max_length_cow_str_type() {
97        assert!(ValidateMaxLength::validate_max_length(&Cow::from("abcde"), 5).is_ok());
98    }
99
100    #[test]
101    fn test_validate_string_max_length_os_str_type() {
102        assert!(ValidateMaxLength::validate_max_length(OsStr::new("fo�o"), 4).is_ok());
103    }
104
105    #[test]
106    fn test_validate_string_max_length_os_string_type() {
107        assert!(ValidateMaxLength::validate_max_length(&OsString::from("fo�o"), 4).is_ok());
108    }
109
110    #[test]
111    fn test_validate_string_max_length_path_type() {
112        assert!(ValidateMaxLength::validate_max_length(&Path::new("./foo/bar.txt"), 13).is_ok());
113    }
114
115    #[test]
116    fn test_validate_string_max_length_path_buf_type() {
117        assert!(
118            ValidateMaxLength::validate_max_length(&PathBuf::from("./foo/bar.txt"), 13).is_ok()
119        );
120    }
121}