1#![warn(missing_docs)]
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub enum SchemaType {
14 String,
16 Integer,
18 Number,
20 Boolean,
22 Array,
24 Object,
26 Null,
28}
29
30impl Default for SchemaType {
31 fn default() -> Self {
33 Self::Object
34 }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
39pub struct Schema {
40 pub title: Option<String>,
42 pub description: Option<String>,
44 pub schema_type: SchemaType,
46 pub properties: Option<std::collections::BTreeMap<String, Schema>>,
48 pub required: Option<Vec<String>>,
50 pub items: Option<Box<Schema>>,
52 pub enum_values: Option<Vec<String>>,
54 pub default: Option<String>,
56 pub example: Option<String>,
58 pub nullable: bool,
60 pub read_only: bool,
62 pub write_only: bool,
64 pub minimum: Option<f64>,
66 pub maximum: Option<f64>,
68 pub min_length: Option<usize>,
70 pub max_length: Option<usize>,
72 pub pattern: Option<String>,
74 pub format: Option<String>,
76 pub one_of: Option<Vec<Schema>>,
78 pub any_of: Option<Vec<Schema>>,
80 pub all_of: Option<Vec<Schema>>,
82}
83
84impl Default for Schema {
85 fn default() -> Self {
87 Self {
88 title: None,
89 description: None,
90 schema_type: SchemaType::Object,
91 properties: None,
92 required: None,
93 items: None,
94 enum_values: None,
95 default: None,
96 example: None,
97 nullable: false,
98 read_only: false,
99 write_only: false,
100 minimum: None,
101 maximum: None,
102 min_length: None,
103 max_length: None,
104 pattern: None,
105 format: None,
106 one_of: None,
107 any_of: None,
108 all_of: None,
109 }
110 }
111}
112
113impl Schema {
114 pub fn string() -> Self {
116 Self { schema_type: SchemaType::String, ..Default::default() }
117 }
118
119 pub fn integer() -> Self {
121 Self { schema_type: SchemaType::Integer, ..Default::default() }
122 }
123
124 pub fn number() -> Self {
126 Self { schema_type: SchemaType::Number, ..Default::default() }
127 }
128
129 pub fn boolean() -> Self {
131 Self { schema_type: SchemaType::Boolean, ..Default::default() }
132 }
133
134 pub fn array(items: Schema) -> Self {
136 Self { schema_type: SchemaType::Array, items: Some(Box::new(items)), ..Default::default() }
137 }
138
139 pub fn object() -> Self {
141 Self { schema_type: SchemaType::Object, properties: Some(std::collections::BTreeMap::new()), ..Default::default() }
142 }
143
144 pub fn title(mut self, title: impl Into<String>) -> Self {
146 self.title = Some(title.into());
147 self
148 }
149
150 pub fn description(mut self, desc: impl Into<String>) -> Self {
152 self.description = Some(desc.into());
153 self
154 }
155
156 pub fn property(mut self, name: impl Into<String>, schema: Schema) -> Self {
158 let properties = self.properties.get_or_insert_with(std::collections::BTreeMap::new);
159 properties.insert(name.into(), schema);
160 self
161 }
162
163 pub fn required(mut self, fields: Vec<&str>) -> Self {
165 self.required = Some(fields.into_iter().map(String::from).collect());
166 self
167 }
168
169 pub fn enum_values(mut self, values: Vec<impl Into<String>>) -> Self {
171 self.enum_values = Some(values.into_iter().map(Into::into).collect());
172 self
173 }
174
175 pub fn with_default(mut self, value: impl Into<String>) -> Self {
177 self.default = Some(value.into());
178 self
179 }
180
181 pub fn example(mut self, value: impl Into<String>) -> Self {
183 self.example = Some(value.into());
184 self
185 }
186
187 pub fn format(mut self, format: impl Into<String>) -> Self {
189 self.format = Some(format.into());
190 self
191 }
192
193 pub fn pattern(mut self, pattern: impl Into<String>) -> Self {
195 self.pattern = Some(pattern.into());
196 self
197 }
198
199 pub fn min_length(mut self, len: usize) -> Self {
201 self.min_length = Some(len);
202 self
203 }
204
205 pub fn max_length(mut self, len: usize) -> Self {
207 self.max_length = Some(len);
208 self
209 }
210
211 pub fn minimum(mut self, min: f64) -> Self {
213 self.minimum = Some(min);
214 self
215 }
216
217 pub fn maximum(mut self, max: f64) -> Self {
219 self.maximum = Some(max);
220 self
221 }
222
223 pub fn nullable(mut self, nullable: bool) -> Self {
225 self.nullable = nullable;
226 self
227 }
228
229 pub fn read_only(mut self, read_only: bool) -> Self {
231 self.read_only = read_only;
232 self
233 }
234
235 pub fn write_only(mut self, write_only: bool) -> Self {
237 self.write_only = write_only;
238 self
239 }
240
241 pub fn one_of(mut self, schemas: Vec<Schema>) -> Self {
243 self.one_of = Some(schemas);
244 self
245 }
246
247 pub fn any_of(mut self, schemas: Vec<Schema>) -> Self {
249 self.any_of = Some(schemas);
250 self
251 }
252
253 pub fn all_of(mut self, schemas: Vec<Schema>) -> Self {
255 self.all_of = Some(schemas);
256 self
257 }
258
259}
260
261pub trait ToSchema {
265 fn schema() -> Schema;
267}
268
269impl ToSchema for String {
270 fn schema() -> Schema {
271 Schema::string()
272 }
273}
274
275impl ToSchema for i64 {
276 fn schema() -> Schema {
277 Schema::integer()
278 }
279}
280
281impl ToSchema for i32 {
282 fn schema() -> Schema {
283 Schema::integer()
284 }
285}
286
287impl ToSchema for i16 {
288 fn schema() -> Schema {
289 Schema::integer()
290 }
291}
292
293impl ToSchema for i8 {
294 fn schema() -> Schema {
295 Schema::integer()
296 }
297}
298
299impl ToSchema for u64 {
300 fn schema() -> Schema {
301 Schema::integer()
302 }
303}
304
305impl ToSchema for u32 {
306 fn schema() -> Schema {
307 Schema::integer()
308 }
309}
310
311impl ToSchema for u16 {
312 fn schema() -> Schema {
313 Schema::integer()
314 }
315}
316
317impl ToSchema for u8 {
318 fn schema() -> Schema {
319 Schema::integer()
320 }
321}
322
323impl ToSchema for f64 {
324 fn schema() -> Schema {
325 Schema::number()
326 }
327}
328
329impl ToSchema for f32 {
330 fn schema() -> Schema {
331 Schema::number()
332 }
333}
334
335impl ToSchema for bool {
336 fn schema() -> Schema {
337 Schema::boolean()
338 }
339}
340
341impl<T: ToSchema> ToSchema for Vec<T> {
342 fn schema() -> Schema {
343 Schema::array(T::schema())
344 }
345}
346
347impl<T: ToSchema> ToSchema for Option<T> {
348 fn schema() -> Schema {
349 T::schema().nullable(true)
350 }
351}
352