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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#[derive(Debug, Clone, PartialEq)]
pub struct HolderAttr {
pub table: Option<syn::Path>,
pub field: Option<syn::Ident>,
pub place_holder: bool,
pub generate_deserialize: bool,
}
impl HolderAttr {
pub fn parse(attrs: &[syn::Attribute]) -> Self {
let mut table = None;
let mut field = None;
let mut place_holder = false;
let mut generate_deserialize = false;
for attr in attrs {
if let Some(ident) = attr.meta.path().get_ident() {
if ident != "holder" {
continue;
}
} else {
continue;
}
match attr.parse_args().unwrap() {
Attr::Table(path) => {
table = Some(path);
}
Attr::Field(ident) => {
field = Some(ident);
}
Attr::PlaceHolder => {
place_holder = true;
}
Attr::GenerateDeserialize => {
generate_deserialize = true;
}
}
}
HolderAttr {
table,
field,
place_holder,
generate_deserialize,
}
}
}
#[derive(Debug, PartialEq)]
enum Attr {
Table(syn::Path),
Field(syn::Ident),
PlaceHolder,
GenerateDeserialize,
}
impl syn::parse::Parse for Attr {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
let ident: syn::Ident = input.parse()?;
match ident.to_string().as_str() {
"table" => {
let _eq: syn::Token![=] = input.parse()?;
let path = input.parse()?;
Ok(Attr::Table(path))
}
"field" => {
let _eq: syn::Token![=] = input.parse()?;
let ident = input.parse()?;
Ok(Attr::Field(ident))
}
"use_place_holder" => Ok(Attr::PlaceHolder),
"generate_deserialize" => Ok(Attr::GenerateDeserialize),
_ => Err(syn::parse::Error::new(
ident.span(),
"expected `table`, `field`, or `use_place_holder`",
)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_attr_table() {
let attr: Attr = syn::parse_str("table = Tables").unwrap();
assert_eq!(attr, Attr::Table(syn::parse_str("Tables").unwrap()));
let attr: Attr = syn::parse_str("table = ::some::path::to::Tables").unwrap();
assert_eq!(
attr,
Attr::Table(syn::parse_str("::some::path::to::Tables").unwrap())
);
assert!(syn::parse_str::<Attr>("table").is_err());
assert!(syn::parse_str::<Attr>("table =").is_err());
}
#[test]
fn parse_attr_field() {
let attr: Attr = syn::parse_str("field = a").unwrap();
assert_eq!(attr, Attr::Field(syn::parse_str("a").unwrap()));
assert!(syn::parse_str::<Attr>("field = ::some::path").is_err());
assert!(syn::parse_str::<Attr>("field").is_err());
assert!(syn::parse_str::<Attr>("field =").is_err());
}
#[test]
fn parse_attr_place_holder() {
let attr: Attr = syn::parse_str("use_place_holder").unwrap();
assert_eq!(attr, Attr::PlaceHolder);
assert!(syn::parse_str::<Attr>("use_place_holder = true").is_err());
assert!(syn::parse_str::<Attr>("use_place_helder").is_err());
}
}