1#![warn(missing_docs)]
8
9use serde::{Deserialize, Serialize};
10use serde_json;
11
12#[cfg(feature = "yaml")]
13use serde_yaml;
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
17#[serde(rename_all = "lowercase")]
18pub enum SchemaType {
19 String,
21 Integer,
23 Number,
25 Boolean,
27 Array,
29 Object,
31 Null,
33}
34
35impl Default for SchemaType {
36 fn default() -> Self {
38 Self::Object
39 }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
44pub struct Schema {
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub title: Option<String>,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub description: Option<String>,
51 #[serde(rename = "type")]
53 pub schema_type: SchemaType,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub properties: Option<std::collections::BTreeMap<String, Schema>>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub required: Option<Vec<String>>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub items: Option<Box<Schema>>,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub enum_values: Option<Vec<serde_json::Value>>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub default: Option<serde_json::Value>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub example: Option<serde_json::Value>,
72 #[serde(default)]
74 pub nullable: bool,
75 #[serde(default)]
77 pub read_only: bool,
78 #[serde(default)]
80 pub write_only: bool,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub minimum: Option<f64>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub maximum: Option<f64>,
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub min_length: Option<usize>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub max_length: Option<usize>,
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub pattern: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub format: Option<String>,
99 pub one_of: Option<Vec<Schema>>,
101 pub any_of: Option<Vec<Schema>>,
103 pub all_of: Option<Vec<Schema>>,
105}
106
107impl Default for Schema {
108 fn default() -> Self {
110 Self {
111 title: None,
112 description: None,
113 schema_type: SchemaType::Object,
114 properties: None,
115 required: None,
116 items: None,
117 enum_values: None,
118 default: None,
119 example: None,
120 nullable: false,
121 read_only: false,
122 write_only: false,
123 minimum: None,
124 maximum: None,
125 min_length: None,
126 max_length: None,
127 pattern: None,
128 format: None,
129 one_of: None,
130 any_of: None,
131 all_of: None,
132 }
133 }
134}
135
136impl Schema {
137 pub fn string() -> Self {
139 Self { schema_type: SchemaType::String, ..Default::default() }
140 }
141
142 pub fn integer() -> Self {
144 Self { schema_type: SchemaType::Integer, ..Default::default() }
145 }
146
147 pub fn number() -> Self {
149 Self { schema_type: SchemaType::Number, ..Default::default() }
150 }
151
152 pub fn boolean() -> Self {
154 Self { schema_type: SchemaType::Boolean, ..Default::default() }
155 }
156
157 pub fn array(items: Schema) -> Self {
159 Self { schema_type: SchemaType::Array, items: Some(Box::new(items)), ..Default::default() }
160 }
161
162 pub fn object() -> Self {
164 Self { schema_type: SchemaType::Object, properties: Some(std::collections::BTreeMap::new()), ..Default::default() }
165 }
166
167 pub fn title(mut self, title: impl Into<String>) -> Self {
169 self.title = Some(title.into());
170 self
171 }
172
173 pub fn description(mut self, desc: impl Into<String>) -> Self {
175 self.description = Some(desc.into());
176 self
177 }
178
179 pub fn property(mut self, name: impl Into<String>, schema: Schema) -> Self {
181 let properties = self.properties.get_or_insert_with(std::collections::BTreeMap::new);
182 properties.insert(name.into(), schema);
183 self
184 }
185
186 pub fn required(mut self, fields: Vec<&str>) -> Self {
188 self.required = Some(fields.into_iter().map(String::from).collect());
189 self
190 }
191
192 pub fn enum_values(mut self, values: Vec<serde_json::Value>) -> Self {
194 self.enum_values = Some(values);
195 self
196 }
197
198 pub fn with_default(mut self, value: serde_json::Value) -> Self {
200 self.default = Some(value);
201 self
202 }
203
204 pub fn example(mut self, value: serde_json::Value) -> Self {
206 self.example = Some(value);
207 self
208 }
209
210 pub fn format(mut self, format: impl Into<String>) -> Self {
212 self.format = Some(format.into());
213 self
214 }
215
216 pub fn pattern(mut self, pattern: impl Into<String>) -> Self {
218 self.pattern = Some(pattern.into());
219 self
220 }
221
222 pub fn min_length(mut self, len: usize) -> Self {
224 self.min_length = Some(len);
225 self
226 }
227
228 pub fn max_length(mut self, len: usize) -> Self {
230 self.max_length = Some(len);
231 self
232 }
233
234 pub fn minimum(mut self, min: f64) -> Self {
236 self.minimum = Some(min);
237 self
238 }
239
240 pub fn maximum(mut self, max: f64) -> Self {
242 self.maximum = Some(max);
243 self
244 }
245
246 pub fn nullable(mut self, nullable: bool) -> Self {
248 self.nullable = nullable;
249 self
250 }
251
252 pub fn read_only(mut self, read_only: bool) -> Self {
254 self.read_only = read_only;
255 self
256 }
257
258 pub fn write_only(mut self, write_only: bool) -> Self {
260 self.write_only = write_only;
261 self
262 }
263
264 pub fn one_of(mut self, schemas: Vec<Schema>) -> Self {
266 self.one_of = Some(schemas);
267 self
268 }
269
270 pub fn any_of(mut self, schemas: Vec<Schema>) -> Self {
272 self.any_of = Some(schemas);
273 self
274 }
275
276 pub fn all_of(mut self, schemas: Vec<Schema>) -> Self {
278 self.all_of = Some(schemas);
279 self
280 }
281
282
283}
284
285pub trait ToSchema {
289 fn schema() -> Schema;
291}
292
293impl ToSchema for String {
294 fn schema() -> Schema {
295 Schema::string()
296 }
297}
298
299impl ToSchema for i64 {
300 fn schema() -> Schema {
301 Schema::integer()
302 }
303}
304
305impl ToSchema for i32 {
306 fn schema() -> Schema {
307 Schema::integer()
308 }
309}
310
311impl ToSchema for i16 {
312 fn schema() -> Schema {
313 Schema::integer()
314 }
315}
316
317impl ToSchema for i8 {
318 fn schema() -> Schema {
319 Schema::integer()
320 }
321}
322
323impl ToSchema for u64 {
324 fn schema() -> Schema {
325 Schema::integer()
326 }
327}
328
329impl ToSchema for u32 {
330 fn schema() -> Schema {
331 Schema::integer()
332 }
333}
334
335impl ToSchema for u16 {
336 fn schema() -> Schema {
337 Schema::integer()
338 }
339}
340
341impl ToSchema for u8 {
342 fn schema() -> Schema {
343 Schema::integer()
344 }
345}
346
347impl ToSchema for f64 {
348 fn schema() -> Schema {
349 Schema::number()
350 }
351}
352
353impl ToSchema for f32 {
354 fn schema() -> Schema {
355 Schema::number()
356 }
357}
358
359impl ToSchema for bool {
360 fn schema() -> Schema {
361 Schema::boolean()
362 }
363}
364
365impl<T: ToSchema> ToSchema for Vec<T> {
366 fn schema() -> Schema {
367 Schema::array(T::schema())
368 }
369}
370
371impl<T: ToSchema> ToSchema for Option<T> {
372 fn schema() -> Schema {
373 T::schema().nullable(true)
374 }
375}
376
377impl ToSchema for serde_json::Value {
378 fn schema() -> Schema {
379 <Schema as Default>::default()
380 }
381}