taitan_orm_parser/info_parser/
condition_parser.rs

1use 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}