valico/json_schema/validators/
items.rs
1use serde_json::{Value};
2use std::cmp;
3use url;
4
5use super::super::errors;
6use super::super::scope;
7
8#[derive(Debug)]
9pub enum ItemsKind {
10 Schema(url::Url),
11 Array(Vec<url::Url>)
12}
13
14#[derive(Debug)]
15pub enum AdditionalKind {
16 Boolean(bool),
17 Schema(url::Url)
18}
19
20#[allow(missing_copy_implementations)]
21pub struct Items {
22 pub items: Option<ItemsKind>,
23 pub additional: Option<AdditionalKind>
24}
25
26impl super::Validator for Items {
27 fn validate(&self, val: &Value, path: &str, scope: &scope::Scope) -> super::ValidationState {
28 let array = nonstrict_process!(val.as_array(), path);
29
30 let mut state = super::ValidationState::new();
31
32 match self.items {
33 Some(ItemsKind::Schema(ref url)) => {
34 let schema = scope.resolve(url);
37 if schema.is_some() {
38 let schema = schema.unwrap();
39 for (idx, item) in array.iter().enumerate() {
40 let item_path = [path, idx.to_string().as_ref()].join("/");
41 state.append(schema.validate_in(item, item_path.as_ref()));
42 }
43 } else {
44 state.missing.push(url.clone());
45 }
46 },
47 Some(ItemsKind::Array(ref urls)) => {
48 let min = cmp::min(urls.len(), array.len());
49
50 for idx in 0..min {
52 let schema = scope.resolve(&urls[idx]);
53 let item = &array[idx];
54
55 if schema.is_some() {
56 let item_path = [path, idx.to_string().as_ref()].join("/");
57 state.append(schema.unwrap().validate_in(item, item_path.as_ref()))
58 } else {
59 state.missing.push(urls[idx].clone())
60 }
61 }
62
63 if array.len() > urls.len() {
65 match self.additional {
66 Some(AdditionalKind::Boolean(allow)) if allow == false => {
67 state.errors.push(Box::new(
68 errors::Items {
69 path: path.to_string(),
70 detail: "Additional items are not allowed".to_string()
71 }
72 ))
73 },
74 Some(AdditionalKind::Schema(ref url)) => {
75 let schema = scope.resolve(url);
76 if schema.is_some() {
77 let schema = schema.unwrap();
78 for (idx, item) in array[urls.len()..].iter().enumerate() {
79 let item_path = [path, idx.to_string().as_ref()].join("/");
80 state.append(schema.validate_in(item, item_path.as_ref()))
81 }
82 } else {
83 state.missing.push(url.clone())
84 }
85 },
86 _ => ()
87 }
88 }
89 }
90 _ => ()
91 }
92
93 state
94 }
95}