taitan_orm_parser/info_parser/
condition_parser.rs1use crate::attr_parser::{AttrParser, NamedAttribute};
2use crate::condition_def::{ConditionDef, VariantsOrFields};
3use crate::{FieldDef, InputParser};
4use case::CaseExt;
5use std::borrow::Cow;
6use syn::parse::Parser;
7use syn::DeriveInput;
8
9#[derive(PartialEq, Clone, Copy, Default)]
10pub struct ConditionParser;
11
12impl ConditionParser {
13 pub fn parse(input: &DeriveInput) -> ConditionDef {
14 let struct_name = input.ident.to_string();
15 let table_name_attr: Option<NamedAttribute> = AttrParser::extract(&input.attrs, "table");
16 let table_name = if let Some(attr) = &table_name_attr {
17 attr.get_single_value().to_owned()
18 } else {
19 Cow::Owned(struct_name.to_snake())
20 };
21 let serde_attr: Option<NamedAttribute> = AttrParser::extract(&input.attrs, "serde_struct");
22 let serde_structs = serde_attr.map(|attr| attr.values).unwrap_or_default();
23
24 let is_enum = InputParser::is_enum(&input.data);
25 let variants_or_fields = if is_enum {
26 let variants = InputParser::get_enum_variant_defs(&input.data).unwrap();
27 VariantsOrFields::Variants(variants)
28 } else {
29 let fields = InputParser::get_fields(&input.data);
30 let defs = fields
31 .iter()
32 .map(|v| FieldDef::parse(v, false, None, None))
33 .collect();
34 VariantsOrFields::Fields(defs)
35 };
36
37 ConditionDef {
38 struct_name: Cow::Owned(struct_name),
39 table_name,
40 variants_or_fields,
41 }
42 }
43}
44
45#[cfg(test)]
46mod test {
47 use super::*;
48 use crate::{FieldName, NamedVariantDef, ParsedField, TableColumnDef};
49 use syn::parse_quote;
50
51 #[test]
52 fn test_parse_001() {
53 let input = parse_quote! {
54 enum LocationSpec001 {
55 A{name: Expr<String>},
56 }
57 };
58
59 let cond_def = ConditionParser::parse(&input);
60 let field = match &cond_def.variants_or_fields {
61 VariantsOrFields::Variants(v) => v
62 .first()
63 .unwrap()
64 .fields
65 .first()
66 .unwrap()
67 .struct_field
68 .origin_field
69 .clone(),
70 _ => unreachable!(),
71 };
72 let variant = NamedVariantDef {
73 name: "A".to_owned(),
74 named: true,
75 fields: vec![FieldDef {
76 struct_field: ParsedField {
77 name: FieldName::named("name"),
78 rust_type: Cow::Borrowed("Expr < String >"),
79 option_nest_level: 0,
80 is_location_expr: true,
81 is_enum_variant: true,
82 lifetime: None,
83 origin_field: field,
84 },
85 table_column: TableColumnDef {
86 name: None,
87 column_type: None,
88 default_value: None,
89 generated: None,
90 nullable: false,
91 auto_inc: false,
92 },
93 }],
94 };
95 let expected_def = ConditionDef {
96 struct_name: Cow::Borrowed("LocationSpec001"),
97 table_name: Cow::Borrowed("location_spec001"),
98 variants_or_fields: VariantsOrFields::Variants(vec![variant]),
99 };
100 assert_eq!(cond_def, expected_def);
101 }
102
103 #[test]
104 fn test_parse_002() {
105 let input = parse_quote! {
106 enum LocationSpec002 {
107 A(Expr<String>, Expr<String>),
108 }
109 };
110 let cond_def = ConditionParser::parse(&input);
111
112 let field = match &cond_def.variants_or_fields {
113 VariantsOrFields::Variants(v) => v
114 .first()
115 .unwrap()
116 .fields
117 .first()
118 .unwrap()
119 .struct_field
120 .origin_field
121 .clone(),
122 _ => unreachable!(),
123 };
124 let field2 = match &cond_def.variants_or_fields {
125 VariantsOrFields::Variants(v) => v
126 .first()
127 .unwrap()
128 .fields
129 .get(1)
130 .unwrap()
131 .struct_field
132 .origin_field
133 .clone(),
134 _ => unreachable!(),
135 };
136 let variant1 = NamedVariantDef {
137 name: "A".to_owned(),
138 named: false,
139 fields: vec![
140 FieldDef {
141 struct_field: ParsedField {
142 name: FieldName::unnamed(0),
143 rust_type: Cow::Borrowed("Expr < String >"),
144 option_nest_level: 0,
145 is_location_expr: true,
146 is_enum_variant: true,
147 lifetime: None,
148 origin_field: field,
149 },
150 table_column: TableColumnDef {
151 name: Some(Cow::Borrowed("a")),
152 column_type: None,
153 default_value: None,
154 generated: None,
155 nullable: false,
156 auto_inc: false,
157 },
158 },
159 FieldDef {
160 struct_field: ParsedField {
161 name: FieldName::unnamed(1),
162 rust_type: Cow::Borrowed("Expr < String >"),
163 option_nest_level: 0,
164 is_location_expr: true,
165 is_enum_variant: true,
166 lifetime: None,
167 origin_field: field2,
168 },
169 table_column: TableColumnDef {
170 name: Some(Cow::Borrowed("a")),
171 column_type: None,
172 default_value: None,
173 generated: None,
174 nullable: false,
175 auto_inc: false,
176 },
177 },
178 ],
179 };
180
181
182 let expected_def = ConditionDef {
183 struct_name: Cow::Borrowed("LocationSpec002"),
184 table_name: Cow::Borrowed("location_spec002"),
185 variants_or_fields: VariantsOrFields::Variants(vec![variant1]),
186 };
187 assert_eq!(cond_def, expected_def);
188 }
189}