taitan_orm_parser/info_parser/
input_parser.rs

1use crate::{FieldDef};
2use proc_macro2::Span;
3use quote::quote;
4use case::CaseExt;
5use syn::{Data, DataEnum, DataStruct, Error, Field, Fields, FieldsNamed};
6
7pub struct InputParser;
8
9#[derive(Debug, Clone)]
10pub struct NamedVariant {
11    pub name: String,
12    pub named: bool,
13    pub fields: Vec<Field>,
14}
15
16#[derive(Debug, Clone, Default, PartialEq)]
17pub struct NamedVariantDef<'a> {
18    pub name: String,
19    pub named: bool,
20    pub fields: Vec<FieldDef<'a>>,
21}
22
23impl InputParser {
24    pub fn get_fields<'a>(data: &'a Data) -> Vec<&'a Field> {
25        let named_fields_result = Self::get_fields_named(data);
26        if let Ok(named_fields) = named_fields_result {
27            named_fields.named.iter().collect()
28        } else {
29            Vec::new()
30        }
31    }
32
33    // pub fn get_fields_named(data: &Data) -> syn::Result<FieldsNamed> {
34    //     let fields = match data {
35    //         Data::Enum(DataEnum {
36    //             enum_token: token::Enum { span },
37    //             ..
38    //         })
39    //         | Data::Union(DataUnion {
40    //             union_token: token::Union { span },
41    //             ..
42    //         }) => {
43    //             return Err(Error::new(*span, "Expected a `struct`"));
44    //         }
45    //
46    //         Data::Struct(DataStruct {
47    //             fields: Fields::Named(it),
48    //             ..
49    //         }) => it,
50    //
51    //         Data::Struct(_) => {
52    //             return Err(Error::new(
53    //                 Span::call_site(),
54    //                 "Expected a `struct` with named fields",
55    //             ));
56    //         }
57    //     };
58    //     Ok(fields.clone())
59    // }
60
61    pub fn get_fields_named(data: &Data) -> syn::Result<&FieldsNamed> {
62        if let Data::Struct(DataStruct { fields, .. }) = data {
63            match fields {
64                Fields::Named(it) => Ok(it),
65                _ => Err(Error::new(
66                    Span::call_site(),
67                    "Expected a struct with named fields",
68                )),
69            }
70        } else {
71            Err(Error::new(Span::call_site(), "Expected a struct"))
72        }
73    }
74
75    pub fn is_enum(data: &Data) -> bool {
76        if let Data::Enum(DataEnum { .. }) = data {
77            true
78        } else {
79            false
80        }
81    }
82
83    pub fn is_struct(data: &Data) -> bool {
84        if let Data::Struct(DataStruct { .. }) = data {
85            true
86        } else {
87            false
88        }
89    }
90
91    pub fn get_enum_variant(data: &Data) -> syn::Result<Vec<NamedVariant>> {
92        let Data::Enum(DataEnum { ref variants, .. }) = data else {
93            return Err(syn::Error::new_spanned(quote! { enum }, "expect enum"));
94        };
95
96        let mut named_variants = Vec::new();
97        for variant in variants {
98            match &variant.fields {
99                Fields::Named(fields_named) => {
100                    named_variants.push(NamedVariant {
101                        name: variant.ident.to_string(),
102                        named: true,
103                        fields: fields_named.clone().named.into_iter().collect(),
104                    });
105                }
106                Fields::Unnamed(fields_unnamed) => {
107                    named_variants.push(NamedVariant {
108                        name: variant.ident.to_string(),
109                        named: false,
110                        fields: fields_unnamed.clone().unnamed.into_iter().collect(),
111                    });
112                }
113                Fields::Unit => {
114                    named_variants.push(NamedVariant {
115                        name: variant.ident.to_string(),
116                        named: false,
117                        fields: Vec::new(),
118                    });
119                }
120            }
121        }
122
123        if named_variants.is_empty() {
124            Err(Error::new_spanned(
125                quote! { enum },
126                "no variant found in the enum",
127            ))
128        } else {
129            Ok(named_variants)
130        }
131    }
132
133    pub fn get_enum_variant_defs(data: &Data) -> syn::Result<Vec<NamedVariantDef>> {
134        let Data::Enum(DataEnum { ref variants, .. }) = data else {
135            return Err(syn::Error::new_spanned(quote! { enum }, "expect enum"));
136        };
137
138        let mut named_variants = Vec::new();
139        for variant in variants {
140            match &variant.fields {
141                Fields::Named(fields_named) => {
142                    named_variants.push(NamedVariantDef {
143                        name: variant.ident.to_string(),
144                        named: true,
145                        fields: fields_named
146                            .named
147                            .iter()
148                            .map(|f| FieldDef::parse(f, true, None, None))
149                            .collect(),
150                    });
151                }
152                Fields::Unnamed(fields_unnamed) => {
153                    let column_name = variant.ident.to_string().to_snake();
154                    named_variants.push(NamedVariantDef {
155                        name: variant.ident.to_string(),
156                        named: false,
157                        fields: fields_unnamed
158                            .unnamed
159                            .iter().enumerate()
160                            .map(|(idx, f)| FieldDef::parse(f, true, Some(idx), Some(column_name.clone())))
161                            .collect(),
162                    });
163                }
164                Fields::Unit => {
165                    named_variants.push(NamedVariantDef {
166                        name: variant.ident.to_string(),
167                        named: false,
168                        fields: Vec::new(),
169                    });
170                }
171            }
172        }
173
174        if named_variants.is_empty() {
175            Err(Error::new_spanned(
176                quote! { enum },
177                "no variant found in the enum",
178            ))
179        } else {
180            Ok(named_variants)
181        }
182    }
183}