taitan_orm_parser/info_parser/
input_parser.rs1use 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> {
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}