1use super::*;
2use crate::error::{Error, Result};
3use crate::{de::FogDeserializer, element::*, value::Value, value_ref::ValueRef};
4use serde::{Deserialize, Serialize};
5use std::{default::Default, iter::repeat};
6
7#[inline]
8fn is_false(v: &bool) -> bool {
9 !v
10}
11#[inline]
12fn validator_is_any(v: &Validator) -> bool {
13 *v == Validator::Any
14}
15
16#[inline]
17fn u32_is_zero(v: &u32) -> bool {
18 *v == 0
19}
20
21#[inline]
22fn u32_is_max(v: &u32) -> bool {
23 *v == u32::MAX
24}
25
26#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
80#[serde(deny_unknown_fields, default)]
81pub struct ArrayValidator {
82 #[serde(skip_serializing_if = "String::is_empty")]
84 pub comment: String,
85 #[serde(skip_serializing_if = "Vec::is_empty")]
87 pub contains: Vec<Validator>,
88 #[serde(skip_serializing_if = "validator_is_any")]
91 pub items: Box<Validator>,
92 #[serde(skip_serializing_if = "Vec::is_empty")]
96 pub prefix: Vec<Validator>,
97 #[serde(skip_serializing_if = "u32_is_max")]
99 pub max_len: u32,
100 #[serde(skip_serializing_if = "u32_is_zero")]
102 pub min_len: u32,
103 #[serde(rename = "in", skip_serializing_if = "Vec::is_empty")]
105 pub in_list: Vec<Vec<Value>>,
106 #[serde(rename = "nin", skip_serializing_if = "Vec::is_empty")]
108 pub nin_list: Vec<Vec<Value>>,
109 #[serde(skip_serializing_if = "is_false")]
111 pub unique: bool,
112 #[serde(skip_serializing_if = "is_false")]
114 pub query: bool,
115 #[serde(skip_serializing_if = "is_false")]
117 pub array: bool,
118 #[serde(skip_serializing_if = "is_false")]
120 pub contains_ok: bool,
121 #[serde(skip_serializing_if = "is_false")]
123 pub unique_ok: bool,
124 #[serde(skip_serializing_if = "is_false")]
126 pub size: bool,
127}
128
129impl Default for ArrayValidator {
130 fn default() -> Self {
131 Self {
132 comment: String::new(),
133 contains: Vec::new(),
134 items: Box::new(Validator::Any),
135 prefix: Vec::new(),
136 max_len: u32::MAX,
137 min_len: u32::MIN,
138 in_list: Vec::new(),
139 nin_list: Vec::new(),
140 unique: false,
141 query: false,
142 array: false,
143 contains_ok: false,
144 unique_ok: false,
145 size: false,
146 }
147 }
148}
149
150impl ArrayValidator {
151 pub fn new() -> Self {
153 Self::default()
154 }
155
156 pub fn comment(mut self, comment: impl Into<String>) -> Self {
158 self.comment = comment.into();
159 self
160 }
161
162 pub fn contains_add(mut self, validator: Validator) -> Self {
164 self.contains.push(validator);
165 self
166 }
167
168 pub fn items(mut self, items: Validator) -> Self {
170 self.items = Box::new(items);
171 self
172 }
173
174 pub fn prefix_add(mut self, prefix: Validator) -> Self {
176 self.prefix.push(prefix);
177 self
178 }
179
180 pub fn max_len(mut self, max_len: u32) -> Self {
182 self.max_len = max_len;
183 self
184 }
185
186 pub fn min_len(mut self, min_len: u32) -> Self {
188 self.min_len = min_len;
189 self
190 }
191
192 pub fn in_add(mut self, add: impl Into<Vec<Value>>) -> Self {
194 self.in_list.push(add.into());
195 self
196 }
197
198 pub fn nin_add(mut self, add: impl Into<Vec<Value>>) -> Self {
200 self.nin_list.push(add.into());
201 self
202 }
203
204 pub fn unique(mut self, unique: bool) -> Self {
206 self.unique = unique;
207 self
208 }
209
210 pub fn query(mut self, query: bool) -> Self {
212 self.query = query;
213 self
214 }
215
216 pub fn array(mut self, array: bool) -> Self {
218 self.array = array;
219 self
220 }
221
222 pub fn contains_ok(mut self, contains_ok: bool) -> Self {
224 self.contains_ok = contains_ok;
225 self
226 }
227
228 pub fn unique_ok(mut self, unique_ok: bool) -> Self {
230 self.unique_ok = unique_ok;
231 self
232 }
233
234 pub fn size(mut self, size: bool) -> Self {
236 self.size = size;
237 self
238 }
239
240 pub fn build(self) -> Validator {
242 Validator::Array(Box::new(self))
243 }
244
245 pub(crate) fn validate<'de, 'c>(
246 &'c self,
247 types: &'c BTreeMap<String, Validator>,
248 mut parser: Parser<'de>,
249 mut checklist: Option<Checklist<'c>>,
250 ) -> Result<(Parser<'de>, Option<Checklist<'c>>)> {
251 let val_parser = parser.clone();
252 let elem = parser
253 .next()
254 .ok_or_else(|| Error::FailValidate("Expected an array".to_string()))??;
255 let len = if let Element::Array(len) = elem {
256 len
257 } else {
258 return Err(Error::FailValidate(format!(
259 "Expected Array, got {}",
260 elem.name()
261 )));
262 };
263
264 if (len as u32) > self.max_len {
265 return Err(Error::FailValidate(format!(
266 "Array is {} elements, longer than maximum allowed of {}",
267 len, self.max_len
268 )));
269 }
270 if (len as u32) < self.min_len {
271 return Err(Error::FailValidate(format!(
272 "Array is {} elements, shorter than minimum allowed of {}",
273 len, self.min_len
274 )));
275 }
276
277 if self.unique || !self.in_list.is_empty() || !self.nin_list.is_empty() {
279 let mut de = FogDeserializer::from_parser(val_parser);
280 let array = Vec::<ValueRef>::deserialize(&mut de)?;
281
282 if !self.in_list.is_empty() && !self.in_list.iter().any(|v| *v == array) {
283 return Err(Error::FailValidate("Array is not on `in` list".to_string()));
284 }
285
286 if self.nin_list.iter().any(|v| *v == array) {
287 return Err(Error::FailValidate("Array is on `nin` list".to_string()));
288 }
289
290 if self.unique
291 && array
292 .iter()
293 .enumerate()
294 .any(|(index, lhs)| array.iter().skip(index).any(|rhs| lhs == rhs))
295 {
296 return Err(Error::FailValidate(
297 "Array does not contain unique elements".to_string(),
298 ));
299 }
300 }
301
302 let mut contains_result = vec![false; self.contains.len()];
304 let mut validators = self.prefix.iter().chain(repeat(self.items.as_ref()));
305 for _ in 0..len {
306 if !self.contains.is_empty() {
308 self.contains
309 .iter()
310 .zip(contains_result.iter_mut())
311 .for_each(|(validator, passed)| {
312 if !*passed {
313 let result =
314 validator.validate(types, parser.clone(), checklist.clone());
315 if let Ok((_, c)) = result {
316 *passed = true;
317 checklist = c;
318 }
319 }
320 });
321 }
322 let (p, c) = validators
323 .next()
324 .unwrap()
325 .validate(types, parser, checklist)?;
326 parser = p;
327 checklist = c;
328 }
329
330 if !contains_result.iter().all(|x| *x) {
331 let mut err_str = String::from("Array was missing items satisfying `contains` list:");
332 let iter = contains_result
333 .iter()
334 .enumerate()
335 .filter(|(_, pass)| !**pass)
336 .map(|(index, _)| format!(" {},", index));
337 err_str.extend(iter);
338 err_str.pop(); return Err(Error::FailValidate(err_str));
340 }
341 Ok((parser, checklist))
342 }
343
344 fn query_check_self(
345 &self,
346 types: &BTreeMap<String, Validator>,
347 other: &ArrayValidator,
348 ) -> bool {
349 let initial_check = (self.query || (other.in_list.is_empty() && other.nin_list.is_empty()))
350 && (self.array || (other.prefix.is_empty() && validator_is_any(&other.items)))
351 && (self.contains_ok || other.contains.is_empty())
352 && (self.unique_ok || !other.unique)
353 && (self.size || (u32_is_max(&other.max_len) && u32_is_zero(&other.min_len)));
354 if !initial_check {
355 return false;
356 }
357 if self.contains_ok {
358 let contains_ok = other.contains.iter().all(|other| {
359 self.items.query_check(types, other)
360 && self
361 .prefix
362 .iter()
363 .all(|mine| mine.query_check(types, other))
364 });
365 if !contains_ok {
366 return false;
367 }
368 }
369 if self.array {
370 self.items.query_check(types, other.items.as_ref())
372 && self
373 .prefix
374 .iter()
375 .chain(repeat(self.items.as_ref()))
376 .zip(other.prefix.iter().chain(repeat(other.items.as_ref())))
377 .take(self.prefix.len().max(other.prefix.len()))
378 .all(|(mine, other)| mine.query_check(types, other))
379 } else {
380 true
381 }
382 }
383
384 pub(crate) fn query_check(
385 &self,
386 types: &BTreeMap<String, Validator>,
387 other: &Validator,
388 ) -> bool {
389 match other {
390 Validator::Array(other) => self.query_check_self(types, other),
391 Validator::Multi(list) => list.iter().all(|other| match other {
392 Validator::Array(other) => self.query_check_self(types, other),
393 _ => false,
394 }),
395 Validator::Any => true,
396 _ => false,
397 }
398 }
399}
400
401#[cfg(test)]
402mod test {
403 use super::*;
404 use crate::{de::FogDeserializer, ser::FogSerializer};
405
406 #[test]
407 fn ser_default() {
408 let schema = ArrayValidator::default();
410 let mut ser = FogSerializer::default();
411 schema.serialize(&mut ser).unwrap();
412 let expected: Vec<u8> = vec![0x80];
413 let actual = ser.finish();
414 println!("expected: {:x?}", expected);
415 println!("actual: {:x?}", actual);
416 assert_eq!(expected, actual);
417
418 let mut de = FogDeserializer::with_debug(&actual, " ");
419 let decoded = ArrayValidator::deserialize(&mut de).unwrap();
420 println!("{}", de.get_debug().unwrap());
421 assert_eq!(schema, decoded);
422 }
423}