1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use proc_macro2::{self, Ident, Span};
use quote::ToTokens;
use std::borrow::Cow;
use syn;
use syn::spanned::Spanned;
use meta::*;
use util::*;
pub struct Field {
pub ty: syn::Type,
pub name: FieldName,
pub span: Span,
pub sql_type: Option<syn::Type>,
column_name_from_attribute: Option<syn::Ident>,
flags: MetaItem,
}
impl Field {
pub fn from_struct_field(field: &syn::Field, index: usize) -> Self {
let column_name_from_attribute =
MetaItem::with_name(&field.attrs, "column_name").map(|m| m.expect_ident_value());
let name = match field.ident.clone() {
Some(mut x) => {
let span = x.span();
x.set_span(fix_span(span, Span::call_site()));
FieldName::Named(x)
}
None => FieldName::Unnamed(syn::Index {
index: index as u32,
span: Span::call_site(),
}),
};
let sql_type = MetaItem::with_name(&field.attrs, "sql_type")
.and_then(|m| m.ty_value().map_err(Diagnostic::emit).ok());
let flags = MetaItem::with_name(&field.attrs, "diesel")
.unwrap_or_else(|| MetaItem::empty("diesel"));
let span = field.span();
Self {
ty: field.ty.clone(),
column_name_from_attribute,
name,
sql_type,
flags,
span,
}
}
pub fn column_name(&self) -> syn::Ident {
self.column_name_from_attribute
.clone()
.unwrap_or_else(|| match self.name {
FieldName::Named(ref x) => x.clone(),
_ => {
self.span
.error(
"All fields of tuple structs must be annotated with `#[column_name]`",
)
.emit();
Ident::new("unknown_column", self.span)
}
})
}
pub fn has_flag(&self, flag: &str) -> bool {
self.flags.has_flag(flag)
}
pub fn ty_for_deserialize(&self) -> Result<Cow<syn::Type>, Diagnostic> {
if let Some(meta) = self.flags.nested_item("deserialize_as")? {
meta.ty_value().map(Cow::Owned)
} else {
Ok(Cow::Borrowed(&self.ty))
}
}
}
pub enum FieldName {
Named(syn::Ident),
Unnamed(syn::Index),
}
impl FieldName {
pub fn assign(&self, expr: syn::Expr) -> syn::FieldValue {
let span = self.span();
let tokens = quote_spanned!(span=> #self: (#expr));
parse_quote!(#tokens)
}
pub fn access(&self) -> proc_macro2::TokenStream {
let span = self.span();
quote_spanned!(span=> .#self)
}
pub fn span(&self) -> Span {
match *self {
FieldName::Named(ref x) => x.span(),
FieldName::Unnamed(ref x) => x.span,
}
}
}
impl ToTokens for FieldName {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match *self {
FieldName::Named(ref x) => x.to_tokens(tokens),
FieldName::Unnamed(ref x) => x.to_tokens(tokens),
}
}
}