taitan_orm_parser/info_parser/
parsed_field.rs1use crate::info_parser::option_parser::OptionParser;
2use crate::info_parser::TypeParser;
3use crate::{FieldName, LifetimeParser};
4use case::CaseExt;
5use quote::{format_ident, quote, ToTokens};
6use std::borrow::Cow;
7use syn::Field;
8
9#[derive(Debug, PartialEq, Clone)]
10pub struct ParsedField<'a> {
11 pub name: FieldName<'a>,
12 pub rust_type: Cow<'a, str>,
13 pub option_nest_level: usize,
14 pub is_location_expr: bool,
15 pub is_enum_variant: bool,
16 pub lifetime: Option<Cow<'a, str>>,
17 pub origin_field: Field,
18}
19
20#[derive(Debug, Clone, Copy)]
21pub enum FieldTokenType {
22 InnerMostType, InnerVariantExpr, NestedOptionType, VariantExpr, }
27impl<'a> ParsedField<'a> {
28 pub fn parse(field: &Field, is_enum_variant: bool, unnamed_idx: Option<usize>) -> Self {
29 let field_name = if let Some(ident) = field.clone().ident {
30 FieldName::Named(Cow::Owned(ident.to_string()))
31 } else {
32 FieldName::unnamed(unnamed_idx.unwrap())
33 };
34 Self::new(&field, field_name, is_enum_variant)
35 }
36 pub fn new(
37 origin_field: &Field,
38 field_name: FieldName<'a>,
39 is_enum_variant: bool,
40 ) -> ParsedField<'a> {
41 let (field_type, option_nest_level) =
42 OptionParser::get_nested_option_inner_type(&origin_field.ty);
43 let field_type_str = field_type.to_token_stream().to_string();
44 let is_location_expr = TypeParser::is_location_expr(&field_type);
45 let lifetime =
46 LifetimeParser::get_lifetime(&origin_field.ty).map(|l| Cow::Owned(l.to_string()));
47 ParsedField {
48 name: field_name.clone(),
49 rust_type: Cow::Owned(field_type_str.clone()),
50 is_enum_variant,
51 is_location_expr,
52 lifetime,
53 option_nest_level,
54 origin_field: origin_field.clone(),
55 }
56 }
57
58 pub fn get_name(&self) -> Cow<'a, str> {
59 match &self.name {
60 FieldName::Named(n) => n.clone(),
61 FieldName::Unnamed { idx: _, name } => name.clone(),
62 }
63 }
64 pub fn is_option(&self) -> bool {
65 self.option_nest_level > 0
66 }
67 pub fn to_token_stream(&self, token_type: FieldTokenType) -> proc_macro2::TokenStream {
68 let field_name = &self.name.get_name();
69 let field_ident = format_ident!("{}", field_name);
70 let ty = &self.origin_field.ty;
71 let vis = &self.origin_field.vis;
72 let attrs = &self.origin_field.attrs;
73 let (inner_type, _) = OptionParser::get_nested_option_inner_type(ty);
74 return match token_type {
75 FieldTokenType::InnerMostType => {
76 quote! {
77 #(#attrs)*
78 #vis #field_ident :#inner_type
79 }
80 }
81 FieldTokenType::NestedOptionType => {
82 quote! {
83 #(#attrs)*
84 #vis #field_ident :std::option::Option<std::option::Option<#inner_type>>
85 }
86 }
87 FieldTokenType::InnerVariantExpr => {
88 quote! {
89 #(#attrs)*
90 #field_ident : taitan_orm::op::Expr<#inner_type>
91 }
92 }
93 FieldTokenType::VariantExpr => {
94 let enum_variant_name = format_ident!("{}", field_name.to_camel());
95 quote! {
96 #enum_variant_name (
97 #(#attrs)*
98 taitan_orm::op::Expr<#inner_type>
99 )
100 }
101 }
102 };
103 }
104}