1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::collections::HashMap;
use regex::Regex;
use serde_derive::Deserialize;
use serde_derive::Serialize;
use crate::dsl::schema::object_types::ObjectType;
pub mod deserialization;
pub mod compiler;
pub mod object_types;
mod dynamic;
#[derive(Clone, Debug)]
pub struct DocumentRoot {
pub version: u64,
pub schema: Option<Schema>,
}
#[derive(Clone, Debug)]
pub struct SchemaList {
entries: Vec<NamedSchema>,
}
#[derive(Clone, Debug, Serialize)]
pub struct NamedSchema {
pub name: String,
#[serde(flatten)]
pub schema: Schema,
}
#[derive(Clone, Debug)]
pub struct Schema {
pub object_type: ObjectType,
pub annotations: Annotations,
pub children: Option<SchemaList>,
pub dynamic: Option<Box<KeysValues>>,
pub formula: Option<String>,
}
#[derive(Clone, Default, Debug, Deserialize)]
pub struct Annotations {
pub title: Option<String>,
pub help: Option<String>,
pub warning: Option<String>,
pub description: Option<String>,
pub placeholder: Option<String>,
pub widget: Option<Widget>,
pub orderable: Option<bool>,
pub addable: Option<bool>,
pub removable: Option<bool>,
pub hidden: Option<bool>,
#[serde(rename = "readOnly")]
pub readonly: Option<bool>,
#[serde(rename = "writeOnly")]
pub writeonly: Option<bool>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Widget {
Textarea,
Hidden,
Password,
}
#[derive(Clone, Debug)]
pub struct KeysSchema {
pub pattern: Regex,
pub title: Option<String>,
}
#[derive(Clone, Debug)]
pub struct KeysValues {
pub keys: KeysSchema,
pub values: Schema,
}
impl NamedSchema {
pub fn unpack(&self) -> (&str, &Schema) {
(self.name.as_ref(), &self.schema)
}
}
impl SchemaList {
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn all_as_map(&self) -> HashMap<&str, &Schema> {
self.entries().iter().map(|schema| schema.unpack()).collect()
}
pub fn all_names(&self) -> Vec<&str> {
self.entries().iter().map(|schema| schema.name.as_str()).collect()
}
pub fn entries(&self) -> &Vec<NamedSchema> {
&self.entries
}
pub fn required_schema_names(&self) -> Vec<&str> {
self.entries
.iter()
.filter_map(|named_schema| {
let object_type = &named_schema.schema.object_type;
match object_type {
ObjectType::Required(_) => Some(named_schema.name.as_str()),
ObjectType::Optional(_) => None,
}
})
.collect()
}
}
impl Annotations {
pub fn with_title_option(title: Option<String>) -> Annotations {
let default = Annotations::default();
Annotations { title, ..default }
}
}