-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.rs
95 lines (86 loc) · 2.84 KB
/
utils.rs
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
/// Heavily influenced/copied from https://stackoverflow.com/questions/55271857/how-can-i-get-the-t-from-an-optiont-when-using-syn
use syn::{GenericArgument, Path, PathArguments};
pub(crate) fn extract_generic_type_segment<'a>(
path: &'a Path,
possible_matches: &'static [&str],
) -> Option<&'a syn::PathSegment> {
let idents_of_path =
path.segments.iter().fold(String::new(), |mut acc, v| {
acc.push_str(&v.ident.to_string());
acc.push('|');
acc
});
possible_matches
.iter()
.find(|s| &idents_of_path == *s)
.and_then(|_| path.segments.last())
}
pub(crate) fn option_segment(path: &syn::Path) -> Option<&syn::PathSegment> {
static OPTION: &[&str] =
&["Option|", "std|option|Option|", "core|option|Option|"];
extract_generic_type_segment(path, OPTION)
}
pub(crate) fn vec_segment(path: &syn::Path) -> Option<&syn::PathSegment> {
static VECTOR: &[&str] = &["Vec|", "std|vec|Vec|", "alloc|vec|Vec|"];
extract_generic_type_segment(path, VECTOR)
}
pub(crate) fn map_segment(path: &syn::Path) -> Option<&syn::PathSegment> {
static MAP: &[&str] = &["HashMap|", "std|collections|HashMap|"];
extract_generic_type_segment(path, MAP)
}
fn extract_type_path(ty: &syn::Type) -> Option<&syn::Path> {
match *ty {
| syn::Type::Path(ref typepath) if typepath.qself.is_none() => {
Some(&typepath.path)
}
| _ => None,
}
}
pub(crate) fn extract_inner_type_from_container(
ty: &syn::Type,
extractor: fn(&syn::Path) -> Option<&syn::PathSegment>,
) -> Option<&syn::Type> {
extract_type_path(ty)
.and_then(extractor)
.and_then(|path_seg| {
let type_params = &path_seg.arguments;
// It should have only on angle-bracketed param ("<String>"):
match *type_params {
| PathArguments::AngleBracketed(ref params) => {
params.args.first()
}
| _ => None,
}
})
.and_then(|generic_arg| {
match *generic_arg {
| GenericArgument::Type(ref ty) => Some(ty),
| _ => None,