valico/json_dsl/
param.rs

1use regex;
2use url;
3use serde_json::{Value, to_value};
4use serde::{Serialize};
5
6use super::super::json_schema;
7use super::builder;
8use super::coercers;
9use super::validators;
10
11pub struct Param {
12    pub name: String,
13    pub coercer: Option<Box<coercers::Coercer + Send + Sync>>,
14    pub nest: Option<builder::Builder>,
15    pub description: Option<String>,
16    pub allow_null: bool,
17    pub validators: validators::Validators,
18    pub default: Option<Value>,
19    pub schema_builder: Option<Box<Fn(&mut json_schema::Builder) + Send + Sync>>,
20    pub schema_id: Option<url::Url>
21}
22
23unsafe impl Send for Param { }
24
25impl Param {
26
27    pub fn new(name: &str) -> Param {
28        Param {
29            name: name.to_string(),
30            description: None,
31            coercer: None,
32            nest: None,
33            allow_null: false,
34            validators: vec![],
35            default: None,
36            schema_builder: None,
37            schema_id: None
38        }
39    }
40
41    pub fn new_with_coercer(name: &str, coercer: Box<coercers::Coercer  + Send + Sync>) -> Param {
42        Param {
43            name: name.to_string(),
44            description: None,
45            coercer: Some(coercer),
46            nest: None,
47            allow_null: false,
48            validators: vec![],
49            default: None,
50            schema_builder: None,
51            schema_id: None
52        }
53    }
54
55    pub fn new_with_nest(name: &str, coercer: Box<coercers::Coercer + Send + Sync>, nest: builder::Builder) -> Param {
56        Param {
57            name: name.to_string(),
58            description: None,
59            coercer: Some(coercer),
60            nest: Some(nest),
61            allow_null: false,
62            validators: vec![],
63            default: None,
64            schema_builder: None,
65            schema_id: None
66        }
67    }
68
69    pub fn build<F>(name: &str, build_def: F) -> Param where F: FnOnce(&mut Param) {
70        let mut param = Param::new(name);
71        build_def(&mut param);
72
73        param
74    }
75
76    pub fn desc(&mut self, description: &str) {
77        self.description = Some(description.to_string());
78    }
79
80    pub fn schema_id(&mut self, id: url::Url) {
81        self.schema_id = Some(id);
82    }
83
84    pub fn schema<F>(&mut self, build: F) where F: Fn(&mut json_schema::Builder,) + 'static + Send + Sync {
85        self.schema_builder = Some(Box::new(build));
86    }
87
88    pub fn coerce(&mut self, coercer: Box<coercers::Coercer + Send + Sync>) {
89        self.coercer = Some(coercer);
90    }
91
92    pub fn nest<F>(&mut self, nest_def: F) where F: FnOnce(&mut builder::Builder) -> () {
93        self.nest = Some(builder::Builder::build(nest_def));
94    }
95
96    pub fn allow_null(&mut self) {
97        self.allow_null = true;
98    }
99
100    pub fn regex(&mut self, regex: regex::Regex) {
101        self.validators.push(Box::new(regex));
102    }
103
104    pub fn validate(&mut self, validator: Box<validators::Validator + 'static + Send + Sync>) {
105        self.validators.push(validator);
106    }
107
108    pub fn validate_with<F>(&mut self, validator: F) where F: Fn(&Value, &str) -> super::validators::ValidatorResult + 'static + Send+Sync {
109        self.validators.push(Box::new(validator));
110    }
111
112    fn process_validators(&self, val: &Value, path: &str) -> super::super::ValicoErrors {
113        let mut errors = vec![];
114        for validator in self.validators.iter() {
115            match validator.validate(val, path) {
116                Ok(()) => (),
117                Err(validation_errors) => errors.extend(validation_errors)
118            }
119        };
120
121        errors
122    }
123
124    pub fn process(&self, val: &mut Value, path: &str, scope: &Option<&json_schema::Scope>) -> super::ExtendedResult<Option<Value>> {
125        if val.is_null() && self.allow_null {
126            return super::ExtendedResult::new(None)
127        }
128
129        let mut result = super::ExtendedResult::new(None);
130        let mut return_value = None;
131
132        {
133
134            let val = if self.coercer.is_some() {
135                match self.coercer.as_ref().unwrap().coerce(val, path) {
136                    Ok(None) => val,
137                    Ok(Some(new_value)) => {
138                        return_value = Some(new_value);
139                        return_value.as_mut().unwrap()
140                    },
141                    Err(errors) => {
142                        result.state.errors.extend(errors);
143                        return result;
144                    }
145                }
146            } else {
147                val
148            };
149
150            if self.nest.is_some() {
151                let process_state = self.nest.as_ref().unwrap().process_nest(val, path, scope);
152                result.append(process_state);
153            }
154
155            let validation_errors = self.process_validators(val, path);
156            result.state.errors.extend(validation_errors);
157
158            if self.schema_id.is_some() && scope.is_some() {
159                let id = self.schema_id.as_ref().unwrap();
160                let schema = scope.as_ref().unwrap().resolve(id);
161                match schema {
162                    Some(schema) => result.append(schema.validate_in(val, path)),
163                    None => result.state.missing.push(id.clone())
164                }
165            }
166        }
167
168        if return_value.is_some() {
169            result.value = return_value;
170        }
171
172        result
173    }
174}
175
176impl Param {
177    pub fn allow_values<T: Serialize>(&mut self, values: &[T]) {
178        self.validators.push(Box::new(validators::AllowedValues::new(
179            values.iter().map(|v| to_value(v).unwrap()).collect()
180        )));
181    }
182
183    pub fn reject_values<T: Serialize>(&mut self, values: &[T]) {
184        self.validators.push(Box::new(validators::RejectedValues::new(
185            values.iter().map(|v| to_value(v).unwrap()).collect()
186        )));
187    }
188
189    pub fn default<T: Serialize>(&mut self, default: T) {
190        self.default = Some(to_value(&default).unwrap());
191    }
192}