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
172impl fmt::Display for Schema {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 if self.name.is_some() && (self.ty.is_struct() || self.ty.is_reference()) {
175 write!(f, "{}", self.name.as_ref().unwrap())
176 } else {
177 write!(f, "{}", self.ty)
178 }
179 }
180}
181
182impl Deref for Schema {
183 type Target = SchemaType;
184
185 fn deref(&self) -> &Self::Target {
186 &self.ty
187 }
188}
189
190impl DerefMut for Schema {
191 fn deref_mut(&mut self) -> &mut Self::Target {
192 &mut self.ty
193 }
194}
195
196impl From<Schema> for SchemaType {
197 fn from(val: Schema) -> Self {
198 val.ty
199 }
200}
201
202impl Schematic for Schema {}
203
204#[cfg(feature = "serde")]
205fn is_false(value: &bool) -> bool {
206 !value
207}
208
209#[derive(Clone, Debug, Default, PartialEq)]
211#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
212pub struct SchemaField {
213 #[cfg_attr(
214 feature = "serde",
215 serde(default, skip_serializing_if = "Option::is_none")
216 )]
217 pub comment: Option<String>,
218
219 pub schema: Schema,
220
221 #[cfg_attr(
222 feature = "serde",
223 serde(default, skip_serializing_if = "Option::is_none")
224 )]
225 pub deprecated: Option<String>,
226
227 #[cfg_attr(
228 feature = "serde",
229 serde(default, skip_serializing_if = "Option::is_none")
230 )]
231 pub env_var: Option<String>,
232
233 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
234 pub hidden: bool,
235
236 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
237 pub nullable: bool,
238
239 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
240 pub optional: bool,
241
242 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
243 pub read_only: bool,
244
245 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
246 pub write_only: bool,
247}
248
249impl SchemaField {
250 pub fn new(schema: impl Into<Schema>) -> Self {
251 Self {
252 schema: schema.into(),
253 ..Default::default()
254 }
255 }
256}
257
258impl From<SchemaField> for Schema {
259 fn from(val: SchemaField) -> Self {
260 val.schema
261 }
262}
263
264impl From<Schema> for SchemaField {
265 fn from(mut schema: Schema) -> Self {
266 SchemaField {
267 comment: schema.description.take(),
268 schema,
269 ..Default::default()
270 }
271 }
272}
273
274impl Schematic for SchemaField {}