serde_valid/validation/generic/
enumerate.rs1use crate::validation::ValidateCompositedEnumerate;
2use crate::EnumerateError;
3
4pub trait ValidateEnumerate<T> {
47 fn validate_enumerate(&self, enumerate: &[T]) -> Result<(), EnumerateError>;
48}
49
50macro_rules! impl_validate_generic_enumerate_literal {
51 ($type:ty) => {
52 impl ValidateEnumerate<$type> for $type {
53 fn validate_enumerate(&self, enumerate: &[$type]) -> Result<(), EnumerateError> {
54 if enumerate.iter().any(|candidate| candidate == self) {
55 Ok(())
56 } else {
57 Err(EnumerateError::new(enumerate))
58 }
59 }
60 }
61
62 impl<T> ValidateCompositedEnumerate<&[$type]> for T
63 where
64 T: ValidateEnumerate<$type>,
65 {
66 fn validate_composited_enumerate(
67 &self,
68 limit: &[$type],
69 ) -> Result<(), crate::validation::Composited<EnumerateError>> {
70 self.validate_enumerate(limit)
71 .map_err(|error| crate::validation::Composited::Single(error))
72 }
73 }
74 };
75}
76
77impl_validate_generic_enumerate_literal!(i8);
78impl_validate_generic_enumerate_literal!(i16);
79impl_validate_generic_enumerate_literal!(i32);
80impl_validate_generic_enumerate_literal!(i64);
81#[cfg(feature = "i128")]
82impl_validate_generic_enumerate_literal!(i128);
83impl_validate_generic_enumerate_literal!(isize);
84impl_validate_generic_enumerate_literal!(u8);
85impl_validate_generic_enumerate_literal!(u16);
86impl_validate_generic_enumerate_literal!(u32);
87impl_validate_generic_enumerate_literal!(u64);
88#[cfg(feature = "i128")]
89impl_validate_generic_enumerate_literal!(u128);
90impl_validate_generic_enumerate_literal!(usize);
91impl_validate_generic_enumerate_literal!(std::num::NonZeroI8);
92impl_validate_generic_enumerate_literal!(std::num::NonZeroI16);
93impl_validate_generic_enumerate_literal!(std::num::NonZeroI32);
94impl_validate_generic_enumerate_literal!(std::num::NonZeroI64);
95#[cfg(feature = "i128")]
96impl_validate_generic_enumerate_literal!(std::num::NonZeroI128);
97impl_validate_generic_enumerate_literal!(std::num::NonZeroIsize);
98impl_validate_generic_enumerate_literal!(std::num::NonZeroU8);
99impl_validate_generic_enumerate_literal!(std::num::NonZeroU16);
100impl_validate_generic_enumerate_literal!(std::num::NonZeroU32);
101impl_validate_generic_enumerate_literal!(std::num::NonZeroU64);
102#[cfg(feature = "i128")]
103impl_validate_generic_enumerate_literal!(std::num::NonZeroU128);
104impl_validate_generic_enumerate_literal!(std::num::NonZeroUsize);
105impl_validate_generic_enumerate_literal!(f32);
106impl_validate_generic_enumerate_literal!(f64);
107impl_validate_generic_enumerate_literal!(char);
108
109macro_rules! impl_validate_generic_enumerate_str {
110 ($type:ty) => {
111 impl ValidateEnumerate<&'static str> for $type {
112 fn validate_enumerate(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> {
113 if enumerate.iter().any(|candidate| candidate == self) {
114 Ok(())
115 } else {
116 Err(EnumerateError::new(enumerate))
117 }
118 }
119 }
120 };
121}
122
123impl_validate_generic_enumerate_str!(&str);
124impl_validate_generic_enumerate_str!(String);
125impl_validate_generic_enumerate_str!(std::borrow::Cow<'_, str>);
126impl_validate_generic_enumerate_str!(&std::ffi::OsStr);
127impl_validate_generic_enumerate_str!(std::ffi::OsString);
128
129macro_rules! impl_validate_generic_enumerate_path {
130 ($type:ty) => {
131 impl ValidateEnumerate<&'static str> for $type {
132 fn validate_enumerate(&self, enumerate: &[&'static str]) -> Result<(), EnumerateError> {
133 if enumerate
134 .iter()
135 .any(|candidate| &std::path::Path::new(candidate) == self)
136 {
137 Ok(())
138 } else {
139 Err(EnumerateError::new(enumerate))
140 }
141 }
142 }
143 };
144}
145
146impl_validate_generic_enumerate_path!(&std::path::Path);
147impl_validate_generic_enumerate_path!(std::path::PathBuf);
148
149impl<T> ValidateCompositedEnumerate<&[&'static str]> for T
150where
151 T: ValidateEnumerate<&'static str>,
152{
153 fn validate_composited_enumerate(
154 &self,
155 limit: &[&'static str],
156 ) -> Result<(), crate::validation::Composited<EnumerateError>> {
157 self.validate_enumerate(limit)
158 .map_err(crate::validation::Composited::Single)
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn test_validate_integer_vec_type_is_true() {
168 assert!(ValidateEnumerate::validate_enumerate(&1, &[1, 2, 3]).is_ok());
169 }
170
171 #[test]
172 fn test_validate_integer_vec_type_is_false() {
173 assert!(ValidateEnumerate::validate_enumerate(&1, &[2, 3, 4]).is_err());
174 }
175
176 #[test]
177 fn test_validate_float_type_is_true() {
178 assert!(ValidateEnumerate::validate_enumerate(&0.9, &[0.9, 2.3, -3.0]).is_ok());
179 }
180
181 #[test]
182 fn test_validate_float_type_is_false() {
183 assert!(ValidateEnumerate::validate_enumerate(&0.9, &[0.8, 2.3, -3.0]).is_err());
184 }
185
186 #[test]
187 fn test_validate_unsigned_int_type() {
188 assert!(ValidateEnumerate::validate_enumerate(&1, &[-1, 0, 1, 2, 3]).is_ok());
189 }
190
191 #[test]
192 fn test_validate_str_type() {
193 assert!(ValidateEnumerate::validate_enumerate(&'a', &['a', 'b', 'c']).is_ok());
194 }
195
196 #[test]
197 fn test_validate_string_type() {
198 assert!(ValidateEnumerate::validate_enumerate(&'a', &['a', 'b', 'c']).is_ok());
199 }
200
201 #[test]
202 fn test_validate_os_str_type() {
203 assert!(ValidateEnumerate::validate_enumerate(
204 &std::ffi::OsStr::new("a"),
205 &["a", "b", "c"]
206 )
207 .is_ok());
208 }
209
210 #[test]
211 fn test_validate_os_string_type() {
212 assert!(ValidateEnumerate::validate_enumerate(
213 &std::ffi::OsString::from("a"),
214 &["a", "b", "c"]
215 )
216 .is_ok());
217 }
218
219 #[test]
220 fn test_validate_path_type() {
221 assert!(ValidateEnumerate::validate_enumerate(
222 &std::path::Path::new("a"),
223 &["a", "b", "c"]
224 )
225 .is_ok());
226 }
227
228 #[test]
229 fn test_validate_path_buf_type() {
230 assert!(ValidateEnumerate::validate_enumerate(
231 &std::path::PathBuf::from("a"),
232 &["a", "b", "c"]
233 )
234 .is_ok());
235 }
236}