valico/json_schema/
builder.rs

1use jsonway;
2use std::collections;
3use serde_json::value::{Value, to_value};
4use serde::{Serialize, Serializer};
5
6pub struct SchemaArray {
7    items: Vec<Value>
8}
9
10impl SchemaArray {
11    pub fn new() -> SchemaArray {
12        SchemaArray { items: vec![] }
13    }
14
15    pub fn push<F>(&mut self, build: F) where F: FnOnce(&mut Builder) {
16        self.items.push( Builder::build(build).into_json() )
17    }
18}
19
20pub struct SchemaHash {
21    items: collections::HashMap<String, Value>
22}
23
24impl SchemaHash {
25    pub fn new() -> SchemaHash {
26        SchemaHash { items: collections::HashMap::new() }
27    }
28
29    pub fn insert<F>(&mut self, key: &str, build: F) where F: FnOnce(&mut Builder) {
30        self.items.insert(key.to_string(), Builder::build(build).into_json());
31    }
32}
33
34pub struct Dependencies {
35    deps: collections::HashMap<String, Dependency>
36}
37
38impl Dependencies {
39    pub fn new() -> Dependencies {
40        Dependencies {
41            deps: collections::HashMap::new()
42        }
43    }
44
45    pub fn schema<F>(&mut self, property: &str, build: F) where F: FnOnce(&mut Builder) {
46        self.deps.insert(property.to_string(), Dependency::Schema( Builder::build(build).into_json() ));
47    }
48
49    pub fn property(&mut self, property: &str, properties: Vec<String>) {
50        self.deps.insert(property.to_string(), Dependency::Property(properties));
51    }
52
53    pub fn build<F>(build: F) -> Dependencies where F: FnOnce(&mut Dependencies) {
54        let mut deps = Dependencies::new();
55        build(&mut deps);
56        deps
57    }
58}
59
60impl Serialize for Dependencies {
61    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
62        self.deps.serialize(serializer)
63    }
64}
65
66pub enum Dependency {
67    Schema(Value),
68    Property(Vec<String>)
69}
70
71impl Serialize for Dependency {
72    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
73        match self {
74            &Dependency::Schema(ref json) => json.serialize(serializer),
75            &Dependency::Property(ref array) => array.serialize(serializer)
76        }
77    }
78}
79
80/// Builder provides simple DSL to build Schema. It allows you not to use
81/// strings and raw JSON manipulation. It also prevent some kinds of spelling
82/// and type errors.
83pub struct Builder {
84    obj_builder: jsonway::ObjectBuilder
85}
86
87impl Builder {
88    pub fn new() -> Builder {
89        Builder {
90            obj_builder: jsonway::ObjectBuilder::new()
91        }
92    }
93
94    pub fn id(&mut self, url: &str) {
95        self.obj_builder.set("id", url.to_string())
96    }
97
98    pub fn ref_(&mut self, url: &str) {
99        self.obj_builder.set("$ref", url.to_string())
100    }
101
102    pub fn schema(&mut self, url: &str) {
103        self.obj_builder.set("$schema", url.to_string())
104    }
105
106    pub fn desc(&mut self, text: &str) {
107        self.obj_builder.set("description", text.to_string())
108    }
109
110    pub fn title(&mut self, text: &str) {
111        self.obj_builder.set("title", text.to_string())
112    }
113
114    pub fn default<T>(&mut self, default: T) where T: Serialize {
115        self.obj_builder.set("default", default)
116    }
117
118    pub fn multiple_of(&mut self, number: f64) {
119        self.obj_builder.set("multipleOf", number)
120    }
121
122    pub fn maximum(&mut self, number: f64, exclusive: bool) {
123        self.obj_builder.set("maximum", number);
124        if exclusive {
125            self.obj_builder.set("exclusiveMaximum", exclusive)
126        }
127    }
128
129    pub fn minimum(&mut self, number: f64, exclusive: bool) {
130        self.obj_builder.set("minimum", number);
131        if exclusive {
132            self.obj_builder.set("exclusiveMinimum", exclusive)
133        }
134    }
135
136    pub fn max_length(&mut self, number: u64) {
137        self.obj_builder.set("maxLength", number)
138    }
139
140    pub fn min_length(&mut self, number: u64) {
141        self.obj_builder.set("minLength", number)
142    }
143
144    pub fn pattern(&mut self, pattern: &str) {
145        self.obj_builder.set("pattern", pattern.to_string())
146    }
147
148    pub fn format(&mut self, format: &str) {
149        self.obj_builder.set("format", format.to_string())
150    }
151
152    pub fn items_schema<F>(&mut self, build: F) where F: FnOnce(&mut Builder) {
153        self.obj_builder.set("items", Builder::build(build).into_json() )
154    }
155
156    pub fn items_array<F>(&mut self, build: F) where F: FnOnce(&mut SchemaArray) {
157        let mut items = SchemaArray::new();
158        build(&mut items);
159        self.obj_builder.set("items", items.items)
160    }
161
162    pub fn additional_items(&mut self, allow: bool) {
163        self.obj_builder.set("additionalItems", allow)
164    }
165
166    pub fn additional_items_schema<F>(&mut self, build: F) where F: FnOnce(&mut Builder) {
167        self.obj_builder.set("additionalItems", Builder::build(build).into_json())
168    }
169
170    pub fn max_items(&mut self, number: u64) {
171        self.obj_builder.set("maxItems", number)
172    }
173
174    pub fn min_items(&mut self, number: u64) {
175        self.obj_builder.set("minItems", number)
176    }
177
178    pub fn unique_items(&mut self, unique: bool) {
179        self.obj_builder.set("uniqueItems", unique)
180    }
181
182    pub fn max_properties(&mut self, number: u64) {
183        self.obj_builder.set("maxProperties", number)
184    }
185
186    pub fn min_properties(&mut self, number: u64) {
187        self.obj_builder.set("minProperties", number)
188    }
189
190    pub fn required(&mut self, items: Vec<String>) {
191        self.obj_builder.set("required", items)
192    }
193
194    pub fn properties<F>(&mut self, build: F) where F: FnOnce(&mut SchemaHash) {
195        let mut items = SchemaHash::new();
196        build(&mut items);
197        self.obj_builder.set("properties", items.items)
198    }
199
200    pub fn pattern_properties<F>(&mut self, build: F) where F: FnOnce(&mut SchemaHash) {
201        let mut items = SchemaHash::new();
202        build(&mut items);
203        self.obj_builder.set("patternProperties", items.items)
204    }
205
206    pub fn additional_properties(&mut self, allow: bool) {
207        self.obj_builder.set("additionalProperties", allow)
208    }
209
210    pub fn additional_properties_schema<F>(&mut self, build: F) where F: FnOnce(&mut Builder) {
211        self.obj_builder.set("additionalProperties", Builder::build(build).into_json())
212    }
213
214    pub fn dependencies<F>(&mut self, build: F) where F: FnOnce(&mut Dependencies) {
215        self.obj_builder.set("dependencies", Dependencies::build(build))
216    }
217
218    pub fn enum_<F>(&mut self, build: F) where F: FnOnce(&mut jsonway::ArrayBuilder) {
219        self.obj_builder.set("enum", jsonway::array(build).unwrap())
220    }
221
222    pub fn array(&mut self) {
223        self.obj_builder.set("type", super::PrimitiveType::Array.to_string())
224    }
225    pub fn boolean(&mut self) {
226        self.obj_builder.set("type", super::PrimitiveType::Boolean.to_string())
227    }
228    pub fn integer(&mut self) {
229        self.obj_builder.set("type", super::PrimitiveType::Integer.to_string())
230    }
231    pub fn number(&mut self) {
232        self.obj_builder.set("type", super::PrimitiveType::Number.to_string())
233    }
234    pub fn null(&mut self) {
235        self.obj_builder.set("type", super::PrimitiveType::Null.to_string())
236    }
237    pub fn object(&mut self) {
238        self.obj_builder.set("type", super::PrimitiveType::Object.to_string())
239    }
240    pub fn string(&mut self) {
241        self.obj_builder.set("type", super::PrimitiveType::String.to_string())
242    }
243    pub fn type_(&mut self, type_: super::PrimitiveType) {
244        self.obj_builder.set("type", type_.to_string())
245    }
246    pub fn types(&mut self, types: &[super::PrimitiveType]) {
247        self.obj_builder.set("type", to_value(&types.iter().map(|t| t.to_string()).collect::<Vec<String>>()).unwrap())
248    }
249
250    pub fn all_of<F>(&mut self, build: F) where F: FnOnce(&mut SchemaArray) {
251        let mut items = SchemaArray::new();
252        build(&mut items);
253        self.obj_builder.set("allOf", items.items)
254    }
255
256    pub fn any_of<F>(&mut self, build: F) where F: FnOnce(&mut SchemaArray) {
257        let mut items = SchemaArray::new();
258        build(&mut items);
259        self.obj_builder.set("anyOf", items.items)
260    }
261
262    pub fn one_of<F>(&mut self, build: F) where F: FnOnce(&mut SchemaArray) {
263        let mut items = SchemaArray::new();
264        build(&mut items);
265        self.obj_builder.set("oneOf", items.items)
266    }
267
268    pub fn not<F>(&mut self, build: F) where F: FnOnce(&mut Builder) {
269        self.obj_builder.set("not", Builder::build(build).into_json())
270    }
271
272    pub fn build<F>(build: F) -> Builder where F: FnOnce(&mut Builder) {
273        let mut builder = Builder::new();
274        build(&mut builder);
275        builder
276    }
277
278    pub fn into_json(self) -> Value {
279        self.obj_builder.unwrap()
280    }
281}
282
283impl Serialize for Builder {
284    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
285       self.obj_builder.serialize(serializer)
286    }
287}
288
289pub fn schema<F>(build: F) -> Builder where F: FnOnce(&mut Builder) {
290    Builder::build(build)
291}
292
293pub fn schema_box(build: Box<Fn(&mut Builder) + Send>) -> Builder {
294    let mut builder = Builder::new();
295    build(&mut builder);
296    builder
297}