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
use from_attr::FlagOrValue;
use syn::{
punctuated::Punctuated, spanned::Spanned, Attribute, Expr, ExprLit, Lit, Meta, MetaNameValue,
Token,
};
pub(crate) struct SerdeAttr {
pub(crate) rename: Option<String>,
pub(crate) flatten: bool,
pub(crate) default: FlagOrValue<String>,
}
impl SerdeAttr {
pub(crate) fn new(attrs: &[Attribute]) -> Self {
let mut rename = None;
let mut flatten = false;
let mut default = FlagOrValue::None;
for attr in attrs {
if !attr.path().is_ident("serde") {
continue;
}
let Ok(meta_list) = attr.meta.require_list() else {
continue;
};
let Ok(nested) =
meta_list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
else {
continue;
};
for meta in nested {
let (path, ident) = {
let path = meta.path();
let Some(ident) = path.get_ident() else {
continue;
};
(path.span(), ident.to_string())
};
match ident.as_str() {
"rename" => match &meta {
Meta::NameValue(MetaNameValue {
value:
Expr::Lit(ExprLit {
lit: Lit::Str(lit_str),
..
}),
..
}) => {
rename = Some(lit_str.value());
}
_ => continue,
},
"flatten" => match &meta {
Meta::Path(_) => {
flatten = true;
}
_ => continue,
},
"default" => match &meta {
Meta::Path(_) => {
default = FlagOrValue::Flag { path };
}
Meta::NameValue(MetaNameValue {
value:
Expr::Lit(ExprLit {
lit: Lit::Str(lit_str),
..
}),
..
}) => {
default = FlagOrValue::Value {
path,
value: lit_str.value(),
};
}
_ => {
continue;
}
},
_ => continue,
}
}
}
Self {
rename,
flatten,
default,
}
}
}