/
lib.rs
174 lines (157 loc) · 6.01 KB
/
lib.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
mod classes;
mod com_methods;
mod constants;
mod delegates;
mod enums;
mod extensions;
mod functions;
mod gen;
mod handles;
mod implements;
mod interfaces;
mod iterators;
mod method_names;
mod structs;
mod winrt_methods;
pub use gen::*;
use metadata::reader::*;
use method_names::*;
use std::collections::*;
use std::fmt::Write;
use tokens::*;
pub fn namespace(gen: &Gen, tree: &Tree) -> String {
let mut tokens = TokenStream::new();
for (name, tree) in &tree.nested {
let name = to_ident(name);
let namespace = tree.namespace[tree.namespace.find('.').unwrap() + 1..].replace('.', "_");
if gen.cfg {
tokens.combine("e! { #[cfg(feature = #namespace)] });
}
tokens.combine("e! { pub mod #name; });
}
let mut functions = BTreeMap::<&str, BTreeMap<&str, TokenStream>>::new();
let mut types = BTreeMap::<TypeKind, BTreeMap<&str, TokenStream>>::new();
for def in gen.reader.namespace_types(tree.namespace) {
let type_name = gen.reader.type_def_type_name(def);
if CORE_TYPES.iter().any(|(x, _)| x == &type_name) {
continue;
}
let name = type_name.name;
let kind = gen.reader.type_def_kind(def);
match kind {
TypeKind::Class => {
if gen.reader.type_def_flags(def).winrt() {
types.entry(kind).or_default().insert(name, classes::gen(gen, def));
} else {
for method in gen.reader.type_def_methods(def) {
let name = gen.reader.method_def_name(method);
let extern_abi = gen.reader.method_def_extern_abi(method);
functions.entry(extern_abi).or_default().entry(name).or_default().combine(&functions::gen(gen, method));
}
for field in gen.reader.type_def_fields(def) {
let name = gen.reader.field_name(field);
types.entry(kind).or_default().entry(name).or_default().combine(&constants::gen(gen, field));
}
}
}
TypeKind::Interface => types.entry(kind).or_default().entry(name).or_default().combine(&interfaces::gen(gen, def)),
TypeKind::Enum => types.entry(kind).or_default().entry(name).or_default().combine(&enums::gen(gen, def)),
TypeKind::Struct => {
if gen.reader.type_def_fields(def).next().is_none() {
if let Some(guid) = gen.reader.type_def_guid(def) {
let ident = to_ident(name);
let value = gen.guid(&guid);
let guid = gen.type_name(&Type::GUID);
let constant = quote! { pub const #ident: #guid = #value; };
types.entry(TypeKind::Class).or_default().entry(name).or_default().combine(&constant);
continue;
}
}
types.entry(kind).or_default().entry(name).or_default().combine(&structs::gen(gen, def));
}
TypeKind::Delegate => types.entry(kind).or_default().entry(name).or_default().combine(&delegates::gen(gen, def)),
}
}
for (extern_abi, functions) in functions {
let functions = functions.values();
if gen.sys {
tokens.combine("e! {
#[cfg_attr(windows, link(name = "windows"))]
extern #extern_abi {
#(#functions)*
}
});
} else {
tokens.combine("e! {
#(#functions)*
});
}
}
for ty in types.values().flat_map(|v| v.values()) {
tokens.combine(ty);
}
if tree.namespace == "Windows.Win32.UI.WindowsAndMessaging" {
tokens.combine("e! {
#[cfg(target_pointer_width = "32")]
#[cfg(feature = "Win32_Foundation")]
pub use SetWindowLongA as SetWindowLongPtrA;
#[cfg(target_pointer_width = "32")]
#[cfg(feature = "Win32_Foundation")]
pub use GetWindowLongA as GetWindowLongPtrA;
#[cfg(target_pointer_width = "32")]
#[cfg(feature = "Win32_Foundation")]
pub use SetWindowLongW as SetWindowLongPtrW;
#[cfg(target_pointer_width = "32")]
#[cfg(feature = "Win32_Foundation")]
pub use GetWindowLongW as GetWindowLongPtrW;
});
}
tokens.into_string()
}
pub fn namespace_impl(gen: &Gen, tree: &Tree) -> String {
let mut types = BTreeMap::<&str, TokenStream>::new();
for def in gen.reader.namespace_types(tree.namespace) {
let type_name = gen.reader.type_def_type_name(def);
if CORE_TYPES.iter().any(|(x, _)| x == &type_name) {
continue;
}
if gen.reader.type_def_kind(def) != TypeKind::Interface {
continue;
}
let tokens = implements::gen(gen, def);
if !tokens.is_empty() {
types.insert(type_name.name, tokens);
}
}
let types = types.values();
let tokens = quote! {
#(#types)*
};
tokens.into_string()
}
pub fn component(namespace: &str, files: &[File]) -> String {
let reader = &Reader::new(files);
let tree = reader.tree(namespace, &[]).expect("Namespace not found");
let mut gen = Gen::new(reader);
gen.namespace = tree.namespace;
gen.component = true;
let mut bindings = crate::namespace(&gen, &tree);
bindings.push_str(&namespace_impl(&gen, &tree));
bindings
}
/// Expand a possibly empty generics list with a new generic
fn expand_generics(generics: TokenStream, new: TokenStream) -> TokenStream {
if generics.is_empty() {
quote!(#new)
} else {
quote!(#generics, #new)
}
}
/// Expand a possibly emppty where clause with a new generic constraint
fn expand_where_clause(where_clause: TokenStream, generic: TokenStream) -> TokenStream {
if where_clause.is_empty() {
quote!(where #generic)
} else {
quote!(#where_clause #generic)
}
}