schematic_types/
schema.rs1use crate::*;
2use std::fmt;
3use std::ops::{Deref, DerefMut};
4
5#[derive(Clone, Debug, Default, PartialEq)]
7#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
8pub struct Schema {
9 #[cfg_attr(
10 feature = "serde",
11 serde(default, skip_serializing_if = "Option::is_none")
12 )]
13 pub deprecated: Option<String>,
14
15 #[cfg_attr(
16 feature = "serde",
17 serde(default, skip_serializing_if = "Option::is_none")
18 )]
19 pub description: Option<String>,
20
21 #[cfg_attr(
22 feature = "serde",
23 serde(default, skip_serializing_if = "Option::is_none")
24 )]
25 pub name: Option<String>,
26
27 #[cfg_attr(feature = "serde", serde(default, skip_serializing))]
28 pub nullable: bool,
29
30 pub ty: SchemaType,
31}
32
33impl Schema {
34 pub fn new(ty: impl Into<SchemaType>) -> Self {
36 Self {
37 ty: ty.into(),
38 ..Default::default()
39 }
40 }
41
42 pub fn array(value: ArrayType) -> Self {
44 Self::new(SchemaType::Array(Box::new(value)))
45 }
46
47 pub fn boolean(value: BooleanType) -> Self {
49 Self::new(SchemaType::Boolean(Box::new(value)))
50 }
51
52 pub fn enumerable(value: EnumType) -> Self {
54 Self::new(SchemaType::Enum(Box::new(value)))
55 }
56
57 pub fn float(value: FloatType) -> Self {
59 Self::new(SchemaType::Float(Box::new(value)))
60 }
61
62 pub fn integer(value: IntegerType) -> Self {
64 Self::new(SchemaType::Integer(Box::new(value)))
65 }
66
67 pub fn literal(value: LiteralType) -> Self {
69 Self::new(SchemaType::Literal(Box::new(value)))
70 }
71
72 pub fn literal_value(value: LiteralValue) -> Self {
74 Self::new(SchemaType::Literal(Box::new(LiteralType::new(value))))
75 }
76
77 pub fn object(value: ObjectType) -> Self {
79 Self::new(SchemaType::Object(Box::new(value)))
80 }
81
82 pub fn string(value: StringType) -> Self {
84 Self::new(SchemaType::String(Box::new(value)))
85 }
86
87 pub fn structure(value: StructType) -> Self {
89 Self::new(SchemaType::Struct(Box::new(value)))
90 }
91
92 pub fn tuple(value: TupleType) -> Self {
94 Self::new(SchemaType::Tuple(Box::new(value)))
95 }
96
97 pub fn union(value: UnionType) -> Self {
99 Self::new(SchemaType::Union(Box::new(value)))
100 }
101
102 pub fn null() -> Self {
104 Self::new(SchemaType::Null)
105 }
106
107 pub fn unknown() -> Self {
109 Self::new(SchemaType::Unknown)
110 }
111
112 pub fn nullify(&mut self) {
115 if self.nullable {
116 return;
118 }
119
120 self.nullable = true;
121
122 if let SchemaType::Union(inner) = &mut self.ty {
123 if self.name.is_none() {
126 if !inner.variants_types.iter().any(|t| t.is_null()) {
127 inner.variants_types.push(Box::new(Schema::null()));
128 }
129
130 return;
131 }
132 }
133
134 let mut new_schema = Schema::new(std::mem::replace(&mut self.ty, SchemaType::Unknown));
136 new_schema.name = self.name.take();
137 new_schema.description.clone_from(&self.description);
138 new_schema.deprecated.clone_from(&self.deprecated);
139
140 self.ty = SchemaType::Union(Box::new(UnionType::new_any([new_schema, Schema::null()])));
141 }
142
143 pub fn partialize(&mut self) {
146 match &mut self.ty {
147 SchemaType::Array(inner) => inner.items_type.partialize(),
148 SchemaType::Object(inner) => inner.value_type.partialize(),
149 SchemaType::Struct(inner) => {
150 inner.partial = true;
151 }
152 SchemaType::Union(inner) => {
153 inner.partial = true;
154
155 let is_nullable = inner.variants_types.iter().any(|t| t.ty.is_null());
158
159 if is_nullable {
160 for item in inner.variants_types.iter_mut() {
161 if !item.is_null() {
162 item.partialize();
163 }
164 }
165 }
166 }
167 _ => {}
168 };
169 }
170
171 pub fn set_deprecated(&mut self, value: impl AsRef<str>) {
173 self.deprecated = Some(value.as_ref().to_owned());
174 }
175
176 pub fn set_description(&mut self, value: impl AsRef<str>) {
178 self.description = Some(value.as_ref().to_owned());
179 }
180
181 pub fn set_name(&mut self, value: impl AsRef<str>) {
183 let name = value.as_ref();
184
185 self.name = Some(name.to_owned());
186 }
187
188 pub fn set_type(&mut self, value: SchemaType) {
190 self.ty = value;
191 }
192
193 pub fn get_nonnull_schema(&self) -> Option<&Schema> {
197 match &self.ty {
198 SchemaType::Null => None,
199 SchemaType::Union(inner) => {
200 for ty in &inner.variants_types {
201 if ty.is_null() {
202 continue;
203 }
204
205 return Some(ty);
206 }
207
208 None
209 }
210 _ => Some(self),
211 }
212 }
213}
214
215impl fmt::Display for Schema {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 if self.name.is_some() && (self.ty.is_struct() || self.ty.is_reference()) {
218 write!(f, "{}", self.name.as_ref().unwrap())
219 } else {
220 write!(f, "{}", self.ty)
221 }
222 }
223}
224
225impl Deref for Schema {
226 type Target = SchemaType;
227
228 fn deref(&self) -> &Self::Target {
229 &self.ty
230 }
231}
232
233impl DerefMut for Schema {
234 fn deref_mut(&mut self) -> &mut Self::Target {
235 &mut self.ty
236 }
237}
238
239impl From<Schema> for SchemaType {
240 fn from(val: Schema) -> Self {
241 val.ty
242 }
243}
244
245impl Schematic for Schema {}
246
247#[cfg(feature = "serde")]
248fn is_false(value: &bool) -> bool {
249 !value
250}
251
252#[derive(Clone, Debug, Default, PartialEq)]
254#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
255pub struct SchemaField {
256 #[cfg_attr(
257 feature = "serde",
258 serde(default, skip_serializing_if = "Vec::is_empty")
259 )]
260 pub aliases: Vec<String>,
261
262 #[cfg_attr(
263 feature = "serde",
264 serde(default, skip_serializing_if = "Option::is_none")
265 )]
266 pub comment: Option<String>,
267
268 pub schema: Schema,
269
270 #[cfg_attr(
271 feature = "serde",
272 serde(default, skip_serializing_if = "Option::is_none")
273 )]
274 pub deprecated: Option<String>,
275
276 #[cfg_attr(
277 feature = "serde",
278 serde(default, skip_serializing_if = "Option::is_none")
279 )]
280 pub env_var: Option<String>,
281
282 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
283 pub flatten: bool,
284
285 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
286 pub hidden: bool,
287
288 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
289 pub nullable: bool,
290
291 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
292 pub optional: bool,
293
294 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
295 pub read_only: bool,
296
297 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
298 pub write_only: bool,
299}
300
301impl SchemaField {
302 pub fn new(schema: impl Into<Schema>) -> Self {
303 Self {
304 schema: schema.into(),
305 ..Default::default()
306 }
307 }
308}
309
310impl From<SchemaField> for Schema {
311 fn from(val: SchemaField) -> Self {
312 val.schema
313 }
314}
315
316impl From<Schema> for SchemaField {
317 fn from(mut schema: Schema) -> Self {
318 SchemaField {
319 comment: schema.description.take(),
320 schema,
321 ..Default::default()
322 }
323 }
324}
325
326impl Schematic for SchemaField {}