apidoc_core/
ty.rs

1use std::collections::{HashMap, HashSet};
2
3use roadblk_attr::ConstraintType;
4use serde::{Deserialize, Serialize};
5
6use apidoc_attr::{prop::ParsedApiDocAttr, serde::ParsedSerdeAttr};
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub enum ApiNumber {
10    I8,
11    I16,
12    I32,
13    I64,
14    I128,
15    U8,
16    U16,
17    U32,
18    USize,
19    U64,
20    U128,
21    F32,
22    F64,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26pub struct ApiEnumer {
27    // 标识符
28    pub ident: String,
29
30    // 名称
31    pub name: Option<String>,
32
33    // 描述
34    pub prop: Option<ParsedApiDocAttr>,
35
36    // 序列化/反序列化
37    pub serde: Vec<ParsedSerdeAttr>,
38
39    // 枚举项: 模型id
40    pub variants: Vec<String>,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
44pub struct ApiNamedField {
45    // 标识符
46    pub ident: String,
47
48    // 名称
49    pub name: Option<String>,
50
51    // 参数说明
52    pub prop: Option<ParsedApiDocAttr>,
53
54    // 是否必传
55    pub option: bool,
56
57    // 类型
58    pub ty: ApiTy,
59
60    // 约束
61    pub constraint: Vec<ConstraintType>,
62
63    // 序列化/反序列化
64    pub serde: Vec<ParsedSerdeAttr>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
68pub struct ApiUnamedField {
69    // 参数名称,元组结构体没有名称
70    pub index: i32,
71
72    // 名称
73    pub name: Option<String>,
74
75    // 参数说明
76    pub prop: Option<ParsedApiDocAttr>,
77
78    // 是否必传
79    pub option: bool,
80
81    // 类型
82    pub ty: ApiTy,
83
84    // 约束
85    pub constraint: Vec<ConstraintType>,
86
87    // 序列化/反序列化
88    pub serde: Vec<ParsedSerdeAttr>,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
92pub enum ApiFields {
93    Named(Vec<ApiNamedField>),
94    Unnamed(Vec<ApiUnamedField>),
95    Unit,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
99pub struct ApiModel {
100    // 标识符
101    pub ident: String,
102
103    // 名称
104    pub name: Option<String>,
105
106    // 描述
107    pub prop: Option<ParsedApiDocAttr>,
108
109    // 值
110    pub value: Option<i32>,
111
112    // 序列化/反序列化
113    pub serde: Vec<ParsedSerdeAttr>,
114
115    // 字段
116    pub fields: ApiFields,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
120pub enum ApiTy {
121    Bool,
122
123    String,
124
125    Number(ApiNumber),
126
127    File,
128
129    Enumer(Box<ApiEnumer>),
130
131    Struct { model_id: String },
132
133    Map(Box<ApiTy>, Box<ApiTy>),
134
135    Set(Box<ApiTy>),
136
137    List(Box<ApiTy>),
138}
139
140pub trait ApiTyTrait {
141    fn api_collect_ty(models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy;
142
143    fn api_option() -> bool {
144        false
145    }
146
147    fn api_model_id() -> String {
148        let type_name = std::any::type_name::<Self>();
149        type_name.to_string()
150    }
151}
152
153macro_rules! impl_ty_number {
154    ($primite: ident, $item: ident) => {
155        impl ApiTyTrait for $primite {
156            fn api_collect_ty(_models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
157                ApiTy::Number(ApiNumber::$item)
158            }
159        }
160    };
161}
162impl_ty_number!(i8, I8);
163impl_ty_number!(i16, I16);
164impl_ty_number!(i32, I32);
165impl_ty_number!(i64, I64);
166impl_ty_number!(i128, I128);
167impl_ty_number!(u8, U8);
168impl_ty_number!(usize, USize);
169impl_ty_number!(u16, U16);
170impl_ty_number!(u32, U32);
171impl_ty_number!(u64, U64);
172impl_ty_number!(u128, U128);
173impl_ty_number!(f32, F32);
174impl_ty_number!(f64, F64);
175
176impl ApiTyTrait for String {
177    fn api_collect_ty(_models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
178        ApiTy::String
179    }
180}
181impl ApiTyTrait for bool {
182    fn api_collect_ty(_models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
183        ApiTy::Bool
184    }
185}
186impl<T: ApiTyTrait> ApiTyTrait for Option<T> {
187    fn api_collect_ty(models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
188        T::api_collect_ty(models)
189    }
190
191    fn api_option() -> bool {
192        true
193    }
194}
195impl<T: ApiTyTrait> ApiTyTrait for Vec<T> {
196    fn api_collect_ty(models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
197        ApiTy::List(Box::new(T::api_collect_ty(models)))
198    }
199}
200impl<T: ApiTyTrait> ApiTyTrait for HashSet<T> {
201    fn api_collect_ty(models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
202        ApiTy::Set(Box::new(T::api_collect_ty(models)))
203    }
204}
205impl<K: ApiTyTrait, V: ApiTyTrait> ApiTyTrait for HashMap<K, V> {
206    fn api_collect_ty(models: &mut HashMap<String, Option<ApiModel>>) -> ApiTy {
207        ApiTy::Map(
208            Box::new(K::api_collect_ty(models)),
209            Box::new(V::api_collect_ty(models)),
210        )
211    }
212}