Skip to main content

itools_schema/
lib.rs

1//! ITools Schema - Schema 定义与构造模块
2//! 
3//! 提供统一的 Schema 定义能力,支持:
4//! - 数据结构 Schema 定义
5//! - Schema 构造
6//! - 兼容 serde metadata
7#![warn(missing_docs)]
8
9use serde::{Deserialize, Serialize};
10
11/// Schema 类型定义
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub enum SchemaType {
14    /// 字符串类型
15    String,
16    /// 整数类型
17    Integer,
18    /// 浮点数类型
19    Number,
20    /// 布尔类型
21    Boolean,
22    /// 数组类型
23    Array,
24    /// 对象类型
25    Object,
26    /// 空值类型
27    Null,
28}
29
30impl Default for SchemaType {
31    /// 创建默认的 Schema 类型(Object)
32    fn default() -> Self {
33        Self::Object
34    }
35}
36
37/// Schema 定义
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
39pub struct Schema {
40    /// Schema 标题
41    pub title: Option<String>,
42    /// Schema 描述
43    pub description: Option<String>,
44    /// Schema 类型
45    pub schema_type: SchemaType,
46    /// 属性定义(仅 Object 类型)
47    pub properties: Option<std::collections::BTreeMap<String, Schema>>,
48    /// 必需属性列表
49    pub required: Option<Vec<String>>,
50    /// 数组元素类型(仅 Array 类型)
51    pub items: Option<Box<Schema>>,
52    /// 枚举值
53    pub enum_values: Option<Vec<String>>,
54    /// 默认值(字符串表示)
55    pub default: Option<String>,
56    /// 示例值(字符串表示)
57    pub example: Option<String>,
58    /// 是否可为空
59    pub nullable: bool,
60    /// 只读
61    pub read_only: bool,
62    /// 只写
63    pub write_only: bool,
64    /// 最小值(Number/Integer)
65    pub minimum: Option<f64>,
66    /// 最大值(Number/Integer)
67    pub maximum: Option<f64>,
68    /// 最小长度(String)
69    pub min_length: Option<usize>,
70    /// 最大长度(String)
71    pub max_length: Option<usize>,
72    /// 正则模式(String)
73    pub pattern: Option<String>,
74    /// 格式(String)
75    pub format: Option<String>,
76    /// 多个类型(用于 one_of)
77    pub one_of: Option<Vec<Schema>>,
78    /// 多个类型(用于 any_of)
79    pub any_of: Option<Vec<Schema>>,
80    /// 多个类型(用于 all_of)
81    pub all_of: Option<Vec<Schema>>,
82}
83
84impl Default for Schema {
85    /// 创建默认的 Schema(Object 类型)
86    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    /// 创建字符串 Schema
115    pub fn string() -> Self {
116        Self { schema_type: SchemaType::String, ..Default::default() }
117    }
118
119    /// 创建整数 Schema
120    pub fn integer() -> Self {
121        Self { schema_type: SchemaType::Integer, ..Default::default() }
122    }
123
124    /// 创建数字 Schema
125    pub fn number() -> Self {
126        Self { schema_type: SchemaType::Number, ..Default::default() }
127    }
128
129    /// 创建布尔 Schema
130    pub fn boolean() -> Self {
131        Self { schema_type: SchemaType::Boolean, ..Default::default() }
132    }
133
134    /// 创建数组 Schema
135    pub fn array(items: Schema) -> Self {
136        Self { schema_type: SchemaType::Array, items: Some(Box::new(items)), ..Default::default() }
137    }
138
139    /// 创建对象 Schema
140    pub fn object() -> Self {
141        Self { schema_type: SchemaType::Object, properties: Some(std::collections::BTreeMap::new()), ..Default::default() }
142    }
143
144    /// 设置标题
145    pub fn title(mut self, title: impl Into<String>) -> Self {
146        self.title = Some(title.into());
147        self
148    }
149
150    /// 设置描述
151    pub fn description(mut self, desc: impl Into<String>) -> Self {
152        self.description = Some(desc.into());
153        self
154    }
155
156    /// 添加属性
157    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    /// 设置必需属性
164    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    /// 设置枚举值
170    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    /// 设置默认值
176    pub fn with_default(mut self, value: impl Into<String>) -> Self {
177        self.default = Some(value.into());
178        self
179    }
180
181    /// 设置示例值
182    pub fn example(mut self, value: impl Into<String>) -> Self {
183        self.example = Some(value.into());
184        self
185    }
186
187    /// 设置格式
188    pub fn format(mut self, format: impl Into<String>) -> Self {
189        self.format = Some(format.into());
190        self
191    }
192
193    /// 设置正则模式
194    pub fn pattern(mut self, pattern: impl Into<String>) -> Self {
195        self.pattern = Some(pattern.into());
196        self
197    }
198
199    /// 设置最小长度
200    pub fn min_length(mut self, len: usize) -> Self {
201        self.min_length = Some(len);
202        self
203    }
204
205    /// 设置最大长度
206    pub fn max_length(mut self, len: usize) -> Self {
207        self.max_length = Some(len);
208        self
209    }
210
211    /// 设置最小值
212    pub fn minimum(mut self, min: f64) -> Self {
213        self.minimum = Some(min);
214        self
215    }
216
217    /// 设置最大值
218    pub fn maximum(mut self, max: f64) -> Self {
219        self.maximum = Some(max);
220        self
221    }
222
223    /// 设置可为空
224    pub fn nullable(mut self, nullable: bool) -> Self {
225        self.nullable = nullable;
226        self
227    }
228
229    /// 设置只读
230    pub fn read_only(mut self, read_only: bool) -> Self {
231        self.read_only = read_only;
232        self
233    }
234
235    /// 设置只写
236    pub fn write_only(mut self, write_only: bool) -> Self {
237        self.write_only = write_only;
238        self
239    }
240
241    /// 设置 oneOf
242    pub fn one_of(mut self, schemas: Vec<Schema>) -> Self {
243        self.one_of = Some(schemas);
244        self
245    }
246
247    /// 设置 anyOf
248    pub fn any_of(mut self, schemas: Vec<Schema>) -> Self {
249        self.any_of = Some(schemas);
250        self
251    }
252
253    /// 设置 allOf
254    pub fn all_of(mut self, schemas: Vec<Schema>) -> Self {
255        self.all_of = Some(schemas);
256        self
257    }
258
259}
260
261/// Schema 生成 trait
262///
263/// 实现此 trait 的类型可以自动生成 Schema。
264pub trait ToSchema {
265    /// 生成 Schema 定义
266    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