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
use syn::{Attribute, Lit, LitStr, Meta, MetaNameValue, NestedMeta};
pub(crate) fn find_attr(attrs: &[Attribute], name: &str) -> Option<Meta> {
attrs.iter().find_map(|a| {
if let Ok(meta) = a.parse_meta() {
if meta.path().is_ident(name) {
Some(meta)
} else {
None
}
} else {
None
}
})
}
pub(crate) fn find_name_attribute<'a>(meta: &'a Meta, name: &str) -> Option<&'a MetaNameValue> {
find_meta(meta, name).map(|meta| match meta {
Meta::NameValue(name_value) => name_value,
_ => panic!("should not happen"),
})
}
pub(crate) fn find_meta<'a>(meta: &'a Meta, name: &str) -> Option<&'a Meta> {
if let Meta::List(list) = meta {
for attr in list.nested.iter() {
if let NestedMeta::Meta(named_meta) = attr {
match named_meta {
Meta::NameValue(meta_name_value) => {
if meta_name_value.path.is_ident(name) {
return Some(named_meta);
}
}
Meta::Path(path) => {
if path.is_ident(name) {
return Some(named_meta);
}
}
Meta::List(_) => {}
}
}
}
}
None
}
pub(crate) fn find_int_name_value(version_meta: &Meta, attr_name: &str) -> Option<u64> {
if let Some(attr) = find_name_attribute(&version_meta, attr_name) {
match &attr.lit {
Lit::Int(version_val) => {
version_val.base10_parse::<u64>().ok()
}
_ => unimplemented!(),
}
} else {
None
}
}
pub(crate) fn find_string_name_value(
version_meta: &Meta,
attr_name: &str,
) -> Option<LitStr> {
if let Some(attr) = find_name_attribute(&version_meta, attr_name) {
match &attr.lit {
Lit::Str(val) => Some(val.clone()),
_ => unimplemented!(),
}
} else {
None
}
}