rschema_core/
schematic.rs

1#![allow(unused_variables)]
2
3use seq_macro::seq;
4use paste::paste;
5
6use std::collections::{
7    HashMap,
8    HashSet,
9};
10
11use crate::{
12    AdditionalProperties,
13    ArrayKeys,
14    Definitions,
15    DefinitionsMap,
16    EnumKeys,
17    Items,
18    NumericKeys,
19    ObjectKeys,
20    Properties,
21    Property,
22    Type,
23    StringKeys,
24};
25
26/// A data structure that can provide any schema informations.
27/// 
28/// It is **deprecated** to implement this manually.
29/// 
30/// Rschema provides `Schematic` implementations for some Rust primitive and standard library types. All of these can be used to generate schema using Rschema.
31/// 
32/// ## Implementations of `Schematic` provided by Rschema
33/// 
34/// - **Primitive types**:
35///   - bool
36///   - i8, i16, i32, i64, isize
37///   - u8, u16, u32, u64, usize
38///   - f32, f64
39///   - char
40///   - str(&str)
41/// - **Compound types**:
42///   - [T; N]
43///   - tuples up to size 12
44/// - **Common standard library types**:
45///   - String
46///   - Option\<T\>
47/// - **Wrapper types**:
48///   - Box\<T\>
49/// - **Collection types**:
50///   - HashMap\<K, V, H\>
51///   - HashSet\<T, H\>
52///   - Vec\<T\>
53/// 
54pub trait Schematic {
55    fn __type(
56        min_length: Option<u64>,
57        max_length: Option<u64>,
58        pattern: Option<String>,
59        format: Option<String>,
60        minimum: Option<i64>,
61        maximum: Option<i64>,
62        multiple_of: Option<i64>,
63        exclusive_minimum: Option<i64>,
64        exclusive_maximum: Option<i64>,
65        min_items: Option<usize>,
66        max_items: Option<usize>,
67        unique_items: Option<bool>,
68    ) -> Type;
69
70    fn __type_no_attr() -> Type {
71        Self::__type(
72            None,
73            None,
74            None,
75            None,
76            None,
77            None,
78            None,
79            None,
80            None,
81            None,
82            None,
83            None,
84        )
85    }
86
87    fn __defs() -> Definitions {
88        Self::__defs_map().build()
89    }
90
91    fn __defs_map() -> DefinitionsMap {
92        DefinitionsMap::new()
93    }
94}
95
96impl<T: Schematic> Schematic for &T {
97    fn __type(
98        min_length: Option<u64>,
99        max_length: Option<u64>,
100        pattern: Option<String>,
101        format: Option<String>,
102        minimum: Option<i64>,
103        maximum: Option<i64>,
104        multiple_of: Option<i64>,
105        exclusive_minimum: Option<i64>,
106        exclusive_maximum: Option<i64>,
107        min_items: Option<usize>,
108        max_items: Option<usize>,
109        unique_items: Option<bool>,
110    ) -> Type {
111        T::__type(
112            min_length,
113            max_length,
114            pattern,
115            format,
116            minimum,
117            maximum,
118            multiple_of,
119            exclusive_minimum,
120            exclusive_maximum,
121            min_items,
122            max_items,
123            unique_items,
124        )
125    }
126
127    fn __type_no_attr() -> Type {
128        T::__type_no_attr()
129    }
130
131    fn __defs_map() -> DefinitionsMap {
132        DefinitionsMap::new()
133    }
134}
135
136impl<T: Schematic> Schematic for &mut T {
137    fn __type(
138        min_length: Option<u64>,
139        max_length: Option<u64>,
140        pattern: Option<String>,
141        format: Option<String>,
142        minimum: Option<i64>,
143        maximum: Option<i64>,
144        multiple_of: Option<i64>,
145        exclusive_minimum: Option<i64>,
146        exclusive_maximum: Option<i64>,
147        min_items: Option<usize>,
148        max_items: Option<usize>,
149        unique_items: Option<bool>,
150    ) -> Type {
151        T::__type(
152            min_length,
153            max_length,
154            pattern,
155            format,
156            minimum,
157            maximum,
158            multiple_of,
159            exclusive_minimum,
160            exclusive_maximum,
161            min_items,
162            max_items,
163            unique_items,
164        )
165    }
166
167    fn __type_no_attr() -> Type {
168        T::__type_no_attr()
169    }
170
171    fn __defs_map() -> DefinitionsMap {
172        DefinitionsMap::new()
173    }
174}
175
176macro_rules! impl_for_str {
177    ($ty:ty) => {
178        impl Schematic for $ty {
179            fn __type(
180                min_length: Option<u64>,
181                max_length: Option<u64>,
182                pattern: Option<String>,
183                format: Option<String>,
184                minimum: Option<i64>,
185                maximum: Option<i64>,
186                multiple_of: Option<i64>,
187                exclusive_minimum: Option<i64>,
188                exclusive_maximum: Option<i64>,
189                min_items: Option<usize>,
190                max_items: Option<usize>,
191                unique_items: Option<bool>,
192            ) -> Type {
193                Type::String(StringKeys {
194                    min_length,
195                    max_length,
196                    pattern,
197                    format,
198                    enm: vec![],
199                })
200            }
201        }
202    };
203}
204
205impl_for_str!(&str);
206impl_for_str!(String);
207
208macro_rules! impl_for_num {
209    ($ty:ty) => {
210        impl Schematic for $ty {
211            fn __type(
212                min_length: Option<u64>,
213                max_length: Option<u64>,
214                pattern: Option<String>,
215                format: Option<String>,
216                minimum: Option<i64>,
217                maximum: Option<i64>,
218                multiple_of: Option<i64>,
219                exclusive_minimum: Option<i64>,
220                exclusive_maximum: Option<i64>,
221                min_items: Option<usize>,
222                max_items: Option<usize>,
223                unique_items: Option<bool>,
224            ) -> Type {
225                Type::Number(NumericKeys {
226                    minimum,
227                    maximum,
228                    multiple_of,
229                    exclusive_minimum,
230                    exclusive_maximum,
231                })
232            }
233        }
234    };
235}
236
237impl_for_num!(i8);
238impl_for_num!(i16);
239impl_for_num!(i32);
240impl_for_num!(i64);
241impl_for_num!(isize);
242impl_for_num!(u8);
243impl_for_num!(u16);
244impl_for_num!(u32);
245impl_for_num!(u64);
246impl_for_num!(usize);
247impl_for_num!(f32);
248impl_for_num!(f64);
249
250impl Schematic for char {
251    fn __type(
252        min_length: Option<u64>,
253        max_length: Option<u64>,
254        pattern: Option<String>,
255        format: Option<String>,
256        minimum: Option<i64>,
257        maximum: Option<i64>,
258        multiple_of: Option<i64>,
259        exclusive_minimum: Option<i64>,
260        exclusive_maximum: Option<i64>,
261        min_items: Option<usize>,
262        max_items: Option<usize>,
263        unique_items: Option<bool>,
264    ) -> Type {
265        Type::String(StringKeys {
266            min_length: Some(1),
267            max_length: Some(1),
268            pattern,
269            format,
270            enm: vec![],
271        })
272    }
273}
274
275impl Schematic for bool {
276    fn __type(
277        min_length: Option<u64>,
278        max_length: Option<u64>,
279        pattern: Option<String>,
280        format: Option<String>,
281        minimum: Option<i64>,
282        maximum: Option<i64>,
283        multiple_of: Option<i64>,
284        exclusive_minimum: Option<i64>,
285        exclusive_maximum: Option<i64>,
286        min_items: Option<usize>,
287        max_items: Option<usize>,
288        unique_items: Option<bool>,
289    ) -> Type {
290        Type::Boolean
291    }
292}
293
294impl Schematic for () {
295    fn __type(
296        min_length: Option<u64>,
297        max_length: Option<u64>,
298        pattern: Option<String>,
299        format: Option<String>,
300        minimum: Option<i64>,
301        maximum: Option<i64>,
302        multiple_of: Option<i64>,
303        exclusive_minimum: Option<i64>,
304        exclusive_maximum: Option<i64>,
305        min_items: Option<usize>,
306        max_items: Option<usize>,
307        unique_items: Option<bool>,
308    ) -> Type {
309        Type::Null
310    }
311}
312
313macro_rules! impls {
314    // $n: Member length
315    // $t: Type parameter
316    // $c: Comma
317    ( $n:expr, $( $t:tt $c:tt )* ) => {
318        impl<$($t:Schematic $c)*> Schematic for ($($t $c)*) {
319            fn __type(
320                min_length: Option<u64>,
321                max_length: Option<u64>,
322                pattern: Option<String>,
323                format: Option<String>,
324                minimum: Option<i64>,
325                maximum: Option<i64>,
326                multiple_of: Option<i64>,
327                exclusive_minimum: Option<i64>,
328                exclusive_maximum: Option<i64>,
329                min_items: Option<usize>,
330                max_items: Option<usize>,
331                unique_items: Option<bool>,
332            ) -> Type {
333                Type::Array(ArrayKeys {
334                    items: Box::new(Items::Tuple(vec![
335                        $(
336                            Property {
337                                title: None,
338                                description: None,
339                                comment: None,
340                                deprecated: None,
341                                ty: <$t as Schematic>::__type_no_attr(),
342                            },
343                        )*
344                    ])),
345                    min_items: Some($n),
346                    max_items: Some($n),
347                    unique_items,
348                })
349            }
350        }
351    }
352}
353
354macro_rules! impls_tuple {
355    ($n:expr) => {
356        seq!(N in 1..=$n {
357            paste! {
358                impls!( $n, #( [<T~N>], )* );
359            }
360        });
361    };
362}
363
364macro_rules! impls_tuple_for {
365    ($n:expr) => {
366        seq!(N in 1..=$n {
367            impls_tuple!(N);
368        });
369    }
370}
371
372// Implementation for tuples with up to 12 members according to `Debug`.
373// See https://qiita.com/9laceef/items/e24f9541ef3924112f6b for these macros.
374impls_tuple_for!(12);
375
376impl<T: Schematic, const N: usize> Schematic for [T; N] {
377    fn __type(
378        min_length: Option<u64>,
379        max_length: Option<u64>,
380        pattern: Option<String>,
381        format: Option<String>,
382        minimum: Option<i64>,
383        maximum: Option<i64>,
384        multiple_of: Option<i64>,
385        exclusive_minimum: Option<i64>,
386        exclusive_maximum: Option<i64>,
387        min_items: Option<usize>,
388        max_items: Option<usize>,
389        unique_items: Option<bool>,
390    ) -> Type {
391        Type::Array(ArrayKeys {
392            items: Box::new(Items::Single(T::__type_no_attr())),
393            min_items: Some(N),
394            max_items: Some(N),
395            unique_items,
396        })
397    }
398}
399
400impl<T: Schematic> Schematic for Option<T> {
401    fn __type(
402        min_length: Option<u64>,
403        max_length: Option<u64>,
404        pattern: Option<String>,
405        format: Option<String>,
406        minimum: Option<i64>,
407        maximum: Option<i64>,
408        multiple_of: Option<i64>,
409        exclusive_minimum: Option<i64>,
410        exclusive_maximum: Option<i64>,
411        min_items: Option<usize>,
412        max_items: Option<usize>,
413        unique_items: Option<bool>,
414    ) -> Type {
415        Type::Enum(EnumKeys {
416            any_of: vec![
417                T::__type_no_attr(),
418                Type::Null,
419            ],
420        })
421    }
422}
423
424impl<T: Schematic> Schematic for Box<T> {
425    fn __type(
426        min_length: Option<u64>,
427        max_length: Option<u64>,
428        pattern: Option<String>,
429        format: Option<String>,
430        minimum: Option<i64>,
431        maximum: Option<i64>,
432        multiple_of: Option<i64>,
433        exclusive_minimum: Option<i64>,
434        exclusive_maximum: Option<i64>,
435        min_items: Option<usize>,
436        max_items: Option<usize>,
437        unique_items: Option<bool>,
438    ) -> Type {
439        T::__type(
440            min_length,
441            max_length,
442            pattern,
443            format,
444            minimum,
445            maximum,
446            multiple_of,
447            exclusive_minimum,
448            exclusive_maximum,
449            min_items,
450            max_items,
451            unique_items,
452        )
453    }
454}
455
456impl<V: Schematic, S> Schematic for HashMap<String, V, S> {
457    fn __type(
458        min_length: Option<u64>,
459        max_length: Option<u64>,
460        pattern: Option<String>,
461        format: Option<String>,
462        minimum: Option<i64>,
463        maximum: Option<i64>,
464        multiple_of: Option<i64>,
465        exclusive_minimum: Option<i64>,
466        exclusive_maximum: Option<i64>,
467        min_items: Option<usize>,
468        max_items: Option<usize>,
469        unique_items: Option<bool>,
470    ) -> Type {
471        Type::Object(ObjectKeys {
472            properties: Properties::new(),
473            required: vec![],
474            additional_properties: Box::new(
475                AdditionalProperties::Complex(V::__type_no_attr())
476            ),
477        })
478    }
479}
480
481impl<T: Schematic, S> Schematic for HashSet<T, S> {
482    fn __type(
483        min_length: Option<u64>,
484        max_length: Option<u64>,
485        pattern: Option<String>,
486        format: Option<String>,
487        minimum: Option<i64>,
488        maximum: Option<i64>,
489        multiple_of: Option<i64>,
490        exclusive_minimum: Option<i64>,
491        exclusive_maximum: Option<i64>,
492        min_items: Option<usize>,
493        max_items: Option<usize>,
494        unique_items: Option<bool>,
495    ) -> Type {
496        Type::Array(ArrayKeys {
497            items: Box::new(Items::Single(T::__type_no_attr())),
498            min_items,
499            max_items,
500            unique_items: Some(true),
501        })
502    }
503}
504
505impl<T: Schematic> Schematic for &[T] {
506    fn __type(
507        min_length: Option<u64>,
508        max_length: Option<u64>,
509        pattern: Option<String>,
510        format: Option<String>,
511        minimum: Option<i64>,
512        maximum: Option<i64>,
513        multiple_of: Option<i64>,
514        exclusive_minimum: Option<i64>,
515        exclusive_maximum: Option<i64>,
516        min_items: Option<usize>,
517        max_items: Option<usize>,
518        unique_items: Option<bool>,
519    ) -> Type {
520        Type::Array(ArrayKeys {
521            items: Box::new(Items::Single(T::__type_no_attr())),
522            min_items,
523            max_items,
524            unique_items,
525        })
526    }
527}
528
529impl<T: Schematic> Schematic for Vec<T> {
530    fn __type(
531        min_length: Option<u64>,
532        max_length: Option<u64>,
533        pattern: Option<String>,
534        format: Option<String>,
535        minimum: Option<i64>,
536        maximum: Option<i64>,
537        multiple_of: Option<i64>,
538        exclusive_minimum: Option<i64>,
539        exclusive_maximum: Option<i64>,
540        min_items: Option<usize>,
541        max_items: Option<usize>,
542        unique_items: Option<bool>,
543    ) -> Type {
544        Type::Array(ArrayKeys {
545            items: Box::new(Items::Single(T::__type_no_attr())),
546            min_items,
547            max_items,
548            unique_items,
549        })
550    }
551}