1use serde::{Serialize, Serializer};
2use serde_json::value::{to_value, Value};
3use std::collections;
4
5pub struct SchemaArray {
6 items: Vec<Value>,
7}
8
9impl SchemaArray {
10 pub fn new() -> SchemaArray {
11 SchemaArray { items: vec![] }
12 }
13
14 pub fn push<F>(&mut self, build: F)
15 where
16 F: FnOnce(&mut Builder),
17 {
18 self.items.push(Builder::build(build).into_json())
19 }
20}
21
22pub struct SchemaHash {
23 items: collections::HashMap<String, Value>,
24}
25
26impl SchemaHash {
27 pub fn new() -> SchemaHash {
28 SchemaHash {
29 items: collections::HashMap::new(),
30 }
31 }
32
33 pub fn insert<F>(&mut self, key: &str, build: F)
34 where
35 F: FnOnce(&mut Builder),
36 {
37 self.items
38 .insert(key.to_string(), Builder::build(build).into_json());
39 }
40}
41
42pub struct Dependencies {
43 deps: collections::HashMap<String, Dependency>,
44}
45
46impl Dependencies {
47 pub fn new() -> Dependencies {
48 Dependencies {
49 deps: collections::HashMap::new(),
50 }
51 }
52
53 pub fn schema<F>(&mut self, property: &str, build: F)
54 where
55 F: FnOnce(&mut Builder),
56 {
57 self.deps.insert(
58 property.to_string(),
59 Dependency::Schema(Builder::build(build).into_json()),
60 );
61 }
62
63 pub fn property(&mut self, property: &str, properties: Vec<String>) {
64 self.deps
65 .insert(property.to_string(), Dependency::Property(properties));
66 }
67
68 pub fn build<F>(build: F) -> Dependencies
69 where
70 F: FnOnce(&mut Dependencies),
71 {
72 let mut deps = Dependencies::new();
73 build(&mut deps);
74 deps
75 }
76}
77
78impl Serialize for Dependencies {
79 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
80 where
81 S: Serializer,
82 {
83 self.deps.serialize(serializer)
84 }
85}
86
87pub enum Dependency {
88 Schema(Value),
89 Property(Vec<String>),
90}
91
92impl Serialize for Dependency {
93 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94 where
95 S: Serializer,
96 {
97 match self {
98 Dependency::Schema(ref json) => json.serialize(serializer),
99 Dependency::Property(ref array) => array.serialize(serializer),
100 }
101 }
102}
103
104pub struct Builder {
108 obj_builder: jsonway::ObjectBuilder,
109}
110
111impl Builder {
112 pub fn new() -> Builder {
113 Builder {
114 obj_builder: jsonway::ObjectBuilder::new(),
115 }
116 }
117
118 pub fn id(&mut self, url: &str) {
119 self.obj_builder.set("$id", url.to_string())
120 }
121
122 pub fn ref_(&mut self, url: &str) {
123 self.obj_builder.set("$ref", url.to_string())
124 }
125
126 pub fn schema(&mut self, url: &str) {
127 self.obj_builder.set("$schema", url.to_string())
128 }
129
130 pub fn desc(&mut self, text: &str) {
131 self.obj_builder.set("description", text.to_string())
132 }
133
134 pub fn title(&mut self, text: &str) {
135 self.obj_builder.set("title", text.to_string())
136 }
137
138 pub fn default<T>(&mut self, default: T)
139 where
140 T: Serialize,
141 {
142 self.obj_builder.set("default", default)
143 }
144
145 pub fn multiple_of(&mut self, number: f64) {
146 self.obj_builder.set("multipleOf", number)
147 }
148
149 pub fn maximum(&mut self, number: f64) {
150 self.obj_builder.set("maximum", number);
151 }
152
153 pub fn exclusive_maximum(&mut self, number: f64) {
154 self.obj_builder.set("exclusiveMaximum", number);
155 }
156
157 pub fn minimum(&mut self, number: f64) {
158 self.obj_builder.set("minimum", number);
159 }
160
161 pub fn exclusive_minimum(&mut self, number: f64) {
162 self.obj_builder.set("exclusiveMinimum", number);
163 }
164
165 pub fn max_length(&mut self, number: u64) {
166 self.obj_builder.set("maxLength", number)
167 }
168
169 pub fn min_length(&mut self, number: u64) {
170 self.obj_builder.set("minLength", number)
171 }
172
173 pub fn pattern(&mut self, pattern: &str) {
174 self.obj_builder.set("pattern", pattern.to_string())
175 }
176
177 pub fn format(&mut self, format: &str) {
178 self.obj_builder.set("format", format.to_string())
179 }
180
181 pub fn items_schema<F>(&mut self, build: F)
182 where
183 F: FnOnce(&mut Builder),
184 {
185 self.obj_builder
186 .set("items", Builder::build(build).into_json())
187 }
188
189 pub fn items_array<F>(&mut self, build: F)
190 where
191 F: FnOnce(&mut SchemaArray),
192 {
193 let mut items = SchemaArray::new();
194 build(&mut items);
195 self.obj_builder.set("items", items.items)
196 }
197
198 pub fn additional_items(&mut self, allow: bool) {
199 self.obj_builder.set("additionalItems", allow)
200 }
201
202 pub fn additional_items_schema<F>(&mut self, build: F)
203 where
204 F: FnOnce(&mut Builder),
205 {
206 self.obj_builder
207 .set("additionalItems", Builder::build(build).into_json())
208 }
209
210 pub fn max_items(&mut self, number: u64) {
211 self.obj_builder.set("maxItems", number)
212 }
213
214 pub fn min_items(&mut self, number: u64) {
215 self.obj_builder.set("minItems", number)
216 }
217
218 pub fn unique_items(&mut self, unique: bool) {
219 self.obj_builder.set("uniqueItems", unique)
220 }
221
222 pub fn max_properties(&mut self, number: u64) {
223 self.obj_builder.set("maxProperties", number)
224 }
225
226 pub fn min_properties(&mut self, number: u64) {
227 self.obj_builder.set("minProperties", number)
228 }
229
230 pub fn required(&mut self, items: Vec<String>) {
231 self.obj_builder.set("required", items)
232 }
233
234 pub fn properties<F>(&mut self, build: F)
235 where
236 F: FnOnce(&mut SchemaHash),
237 {
238 let mut items = SchemaHash::new();
239 build(&mut items);
240 self.obj_builder.set("properties", items.items)
241 }
242
243 pub fn pattern_properties<F>(&mut self, build: F)
244 where
245 F: FnOnce(&mut SchemaHash),
246 {
247 let mut items = SchemaHash::new();
248 build(&mut items);
249 self.obj_builder.set("patternProperties", items.items)
250 }
251
252 pub fn additional_properties(&mut self, allow: bool) {
253 self.obj_builder.set("additionalProperties", allow)
254 }
255
256 pub fn additional_properties_schema<F>(&mut self, build: F)
257 where
258 F: FnOnce(&mut Builder),
259 {
260 self.obj_builder
261 .set("additionalProperties", Builder::build(build).into_json())
262 }
263
264 pub fn dependencies<F>(&mut self, build: F)
265 where
266 F: FnOnce(&mut Dependencies),
267 {
268 self.obj_builder
269 .set("dependencies", Dependencies::build(build))
270 }
271
272 pub fn enum_<F>(&mut self, build: F)
273 where
274 F: FnOnce(&mut jsonway::ArrayBuilder),
275 {
276 self.obj_builder.set("enum", jsonway::array(build).unwrap())
277 }
278
279 pub fn array(&mut self) {
280 self.obj_builder
281 .set("type", super::PrimitiveType::Array.to_string())
282 }
283 pub fn boolean(&mut self) {
284 self.obj_builder
285 .set("type", super::PrimitiveType::Boolean.to_string())
286 }
287 pub fn integer(&mut self) {
288 self.obj_builder
289 .set("type", super::PrimitiveType::Integer.to_string())
290 }
291 pub fn number(&mut self) {
292 self.obj_builder
293 .set("type", super::PrimitiveType::Number.to_string())
294 }
295 pub fn null(&mut self) {
296 self.obj_builder
297 .set("type", super::PrimitiveType::Null.to_string())
298 }
299 pub fn object(&mut self) {
300 self.obj_builder
301 .set("type", super::PrimitiveType::Object.to_string())
302 }
303 pub fn string(&mut self) {
304 self.obj_builder
305 .set("type", super::PrimitiveType::String.to_string())
306 }
307 pub fn type_(&mut self, type_: super::PrimitiveType) {
308 self.obj_builder.set("type", type_.to_string())
309 }
310 pub fn types(&mut self, types: &[super::PrimitiveType]) {
311 self.obj_builder.set(
312 "type",
313 to_value(types.iter().map(|t| t.to_string()).collect::<Vec<String>>()).unwrap(),
314 )
315 }
316
317 pub fn all_of<F>(&mut self, build: F)
318 where
319 F: FnOnce(&mut SchemaArray),
320 {
321 let mut items = SchemaArray::new();
322 build(&mut items);
323 self.obj_builder.set("allOf", items.items)
324 }
325
326 pub fn any_of<F>(&mut self, build: F)
327 where
328 F: FnOnce(&mut SchemaArray),
329 {
330 let mut items = SchemaArray::new();
331 build(&mut items);
332 self.obj_builder.set("anyOf", items.items)
333 }
334
335 pub fn one_of<F>(&mut self, build: F)
336 where
337 F: FnOnce(&mut SchemaArray),
338 {
339 let mut items = SchemaArray::new();
340 build(&mut items);
341 self.obj_builder.set("oneOf", items.items)
342 }
343
344 pub fn not<F>(&mut self, build: F)
345 where
346 F: FnOnce(&mut Builder),
347 {
348 self.obj_builder
349 .set("not", Builder::build(build).into_json())
350 }
351
352 pub fn build<F>(build: F) -> Builder
353 where
354 F: FnOnce(&mut Builder),
355 {
356 let mut builder = Builder::new();
357 build(&mut builder);
358 builder
359 }
360
361 pub fn into_json(self) -> Value {
362 self.obj_builder.unwrap()
363 }
364
365 pub fn content_media_type(&mut self, type_: super::keywords::content_media::ContentMediaType) {
366 self.obj_builder.set("contentMediaType", type_.as_str())
367 }
368
369 pub fn content_encoding(&mut self, type_: super::keywords::content_media::ContentEncoding) {
370 self.obj_builder.set("contentEncoding", type_.as_str())
371 }
372
373 pub fn if_<F>(&mut self, build: F)
374 where
375 F: FnOnce(&mut Builder),
376 {
377 self.obj_builder
378 .set("if", Builder::build(build).into_json())
379 }
380
381 pub fn then_<F>(&mut self, build: F)
382 where
383 F: FnOnce(&mut Builder),
384 {
385 self.obj_builder
386 .set("then", Builder::build(build).into_json())
387 }
388
389 pub fn else_<F>(&mut self, build: F)
390 where
391 F: FnOnce(&mut Builder),
392 {
393 self.obj_builder
394 .set("else", Builder::build(build).into_json())
395 }
396
397 pub fn custom_vocabulary<V: Serialize, N: Into<String>>(&mut self, name: N, value: V) {
398 self.obj_builder.set(name, value);
399 }
400}
401
402impl Serialize for Builder {
403 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
404 where
405 S: Serializer,
406 {
407 self.obj_builder.serialize(serializer)
408 }
409}
410
411pub fn schema<F>(build: F) -> Builder
412where
413 F: FnOnce(&mut Builder),
414{
415 Builder::build(build)
416}
417
418pub fn schema_box(build: Box<dyn Fn(&mut Builder) + Send>) -> Builder {
419 let mut builder = Builder::new();
420 build(&mut builder);
421 builder
422}