/
cfg.rs
117 lines (100 loc) · 3.28 KB
/
cfg.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use super::*;
#[derive(Default, Clone)]
pub struct Cfg {
pub arch: BTreeSet<&'static str>,
pub features: BTreeSet<&'static str>,
}
impl Cfg {
pub fn new() -> Self {
Default::default()
}
pub fn union(&self, other: Self) -> Self {
Self { arch: self.arch.union(&other.arch).cloned().collect(), features: self.features.union(&other.features).cloned().collect() }
}
pub fn and_iterator(&self) -> Self {
let mut combo = self.clone();
combo.features.insert("Windows.Foundation.Collections");
combo
}
pub fn and_async(&self) -> Self {
let mut combo = self.clone();
combo.features.insert("std");
combo.features.insert("Windows.Foundation");
combo
}
pub fn gen_with_doc(&self, gen: &Gen) -> TokenStream {
let doc = self.gen_doc(gen);
let requires = self.gen(gen);
quote! { #doc #requires }
}
pub fn gen_doc(&self, gen: &Gen) -> TokenStream {
if !gen.doc {
quote! {}
} else {
let mut tokens = format!("'{}'", to_feature(gen.namespace));
for features in &self.features {
tokens.push_str(&format!(", '{}'", to_feature(features)));
}
format!(r#"#[doc = "*Required features: {}*"]"#, tokens).into()
}
}
pub fn gen(&self, gen: &Gen) -> TokenStream {
if !gen.cfg {
quote! {}
} else {
let arch = match self.arch.len() {
0 => quote! {},
1 => {
let arch = &self.arch;
quote! { #[cfg(#(target_arch = #arch),*)] }
}
_ => {
let arch = &self.arch;
quote! { #[cfg(any(#(target_arch = #arch),*))] }
}
};
let features = match self.features.len() {
0 => quote! {},
1 => {
let features = self.features.iter().cloned().map(to_feature);
quote! { #[cfg(#(feature = #features)*)] }
}
_ => {
let features = self.features.iter().cloned().map(to_feature);
quote! { #[cfg(all( #(feature = #features),* ))] }
}
};
quote! { #arch #features }
}
}
pub fn gen_not(&self, gen: &Gen) -> TokenStream {
if !gen.cfg || self.features.is_empty() {
quote! {}
} else {
match self.features.len() {
0 => quote! {},
1 => {
let features = self.features.iter().cloned().map(to_feature);
quote! { #[cfg(not(#(feature = #features)*))] }
}
_ => {
let features = self.features.iter().cloned().map(to_feature);
quote! { #[cfg(not(all( #(feature = #features),* )))] }
}
}
}
}
}
fn to_feature(name: &str) -> String {
let mut feature = String::new();
for name in name.split('.').skip(1) {
feature.push_str(name);
feature.push('_');
}
if feature.is_empty() {
feature = name.to_string();
} else {
feature.truncate(feature.len() - 1);
}
feature
}