1use proc_macro2::{Span, TokenStream};
2use syn::spanned::Spanned;
3use syn::{Expr, Field as SynField, Ident, Index, Result, Type};
4
5use crate::attrs::{parse_attributes, AttributeSpanWrapper, FieldAttr, SqlIdentifier};
6
7pub struct Field {
8 pub ty: Type,
9 pub span: Span,
10 pub name: FieldName,
11 column_name: Option<AttributeSpanWrapper<SqlIdentifier>>,
12 pub sql_type: Option<AttributeSpanWrapper<Type>>,
13 pub treat_none_as_default_value: Option<AttributeSpanWrapper<bool>>,
14 pub treat_none_as_null: Option<AttributeSpanWrapper<bool>>,
15 pub serialize_as: Option<AttributeSpanWrapper<Type>>,
16 pub deserialize_as: Option<AttributeSpanWrapper<Type>>,
17 pub select_expression: Option<AttributeSpanWrapper<Expr>>,
18 pub select_expression_type: Option<AttributeSpanWrapper<Type>>,
19 pub embed: Option<AttributeSpanWrapper<bool>>,
20 pub skip_insertion: Option<AttributeSpanWrapper<bool>>,
21 pub skip_update: Option<AttributeSpanWrapper<bool>>,
22}
23
24impl Field {
25 pub fn from_struct_field(field: &SynField, index: usize) -> Result<Self> {
26 let SynField {
27 ident, attrs, ty, ..
28 } = field;
29
30 let mut column_name = None;
31 let mut sql_type = None;
32 let mut serialize_as = None;
33 let mut deserialize_as = None;
34 let mut embed = None;
35 let mut skip_insertion = None;
36 let mut skip_update = None;
37 let mut select_expression = None;
38 let mut select_expression_type = None;
39 let mut treat_none_as_default_value = None;
40 let mut treat_none_as_null = None;
41
42 for attr in parse_attributes(attrs)? {
43 let attribute_span = attr.attribute_span;
44 let ident_span = attr.ident_span;
45 match attr.item {
46 FieldAttr::ColumnName(_, value) => {
47 column_name = Some(AttributeSpanWrapper {
48 item: value,
49 attribute_span,
50 ident_span,
51 })
52 }
53 FieldAttr::SqlType(_, value) => {
54 sql_type = Some(AttributeSpanWrapper {
55 item: Type::Path(value),
56 attribute_span,
57 ident_span,
58 })
59 }
60 FieldAttr::TreatNoneAsDefaultValue(_, value) => {
61 treat_none_as_default_value = Some(AttributeSpanWrapper {
62 item: value.value,
63 attribute_span,
64 ident_span,
65 })
66 }
67 FieldAttr::TreatNoneAsNull(_, value) => {
68 treat_none_as_null = Some(AttributeSpanWrapper {
69 item: value.value,
70 attribute_span,
71 ident_span,
72 })
73 }
74 FieldAttr::SerializeAs(_, value) => {
75 serialize_as = Some(AttributeSpanWrapper {
76 item: Type::Path(value),
77 attribute_span,
78 ident_span,
79 })
80 }
81 FieldAttr::DeserializeAs(_, value) => {
82 deserialize_as = Some(AttributeSpanWrapper {
83 item: Type::Path(value),
84 attribute_span,
85 ident_span,
86 })
87 }
88 FieldAttr::SelectExpression(_, value) => {
89 select_expression = Some(AttributeSpanWrapper {
90 item: value,
91 attribute_span,
92 ident_span,
93 })
94 }
95 FieldAttr::SelectExpressionType(_, value) => {
96 select_expression_type = Some(AttributeSpanWrapper {
97 item: value,
98 attribute_span,
99 ident_span,
100 })
101 }
102 FieldAttr::Embed(_) => {
103 embed = Some(AttributeSpanWrapper {
104 item: true,
105 attribute_span,
106 ident_span,
107 })
108 }
109 FieldAttr::SkipInsertion(_) => {
110 skip_insertion = Some(AttributeSpanWrapper {
111 item: true,
112 attribute_span,
113 ident_span,
114 })
115 }
116 FieldAttr::SkipUpdate(_) => {
117 skip_update = Some(AttributeSpanWrapper {
118 item: true,
119 attribute_span,
120 ident_span,
121 })
122 }
123 }
124 }
125
126 let name = match ident.clone() {
127 Some(x) => FieldName::Named(x),
128 None => FieldName::Unnamed(index.into()),
129 };
130
131 let span = match name {
132 FieldName::Named(ref ident) => ident.span(),
133 FieldName::Unnamed(_) => ty.span(),
134 };
135
136 Ok(Self {
137 ty: ty.clone(),
138 span,
139 name,
140 column_name,
141 sql_type,
142 treat_none_as_default_value,
143 treat_none_as_null,
144 serialize_as,
145 deserialize_as,
146 select_expression,
147 select_expression_type,
148 embed,
149 skip_insertion,
150 skip_update,
151 })
152 }
153
154 pub fn column_name(&self) -> Result<SqlIdentifier> {
155 let identifier = self.column_name.as_ref().map(|a| a.item.clone());
156 if let Some(identifier) = identifier {
157 Ok(identifier)
158 } else {
159 match self.name {
160 FieldName::Named(ref x) => Ok(x.into()),
161 FieldName::Unnamed(ref x) => Err(syn::Error::new(
162 x.span(),
163 "All fields of tuple structs must be annotated with `#[diesel(column_name)]`",
164 )),
165 }
166 }
167 }
168
169 pub fn ty_for_deserialize(&self) -> &Type {
170 if let Some(AttributeSpanWrapper { item: value, .. }) = &self.deserialize_as {
171 value
172 } else {
173 &self.ty
174 }
175 }
176
177 pub(crate) fn embed(&self) -> bool {
178 self.embed.as_ref().map(|a| a.item).unwrap_or(false)
179 }
180
181 pub(crate) fn skip_insertion(&self) -> bool {
182 self.skip_insertion
183 .as_ref()
184 .map(|a| a.item)
185 .unwrap_or(false)
186 }
187
188 pub(crate) fn skip_update(&self) -> bool {
189 self.skip_update.as_ref().map(|a| a.item).unwrap_or(false)
190 }
191}
192
193pub enum FieldName {
194 Named(Ident),
195 Unnamed(Index),
196}
197
198impl quote::ToTokens for FieldName {
199 fn to_tokens(&self, tokens: &mut TokenStream) {
200 match *self {
201 FieldName::Named(ref x) => x.to_tokens(tokens),
202 FieldName::Unnamed(ref x) => x.to_tokens(tokens),
203 }
204 }
205}