Skip to content

Commit dcfbae4

Browse files
committed
windows-bindgen
1 parent 94e1288 commit dcfbae4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+7904
-8197
lines changed

crates/libs/bindgen/Cargo.toml

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
[package]
22
name = "windows-bindgen"
33
version = "0.58.0"
4-
authors = ["Microsoft"]
54
edition = "2021"
6-
rust-version = "1.70"
5+
rust-version = "1.74"
76
license = "MIT OR Apache-2.0"
8-
description = "Windows metadata compiler"
7+
description = "Windows code generator"
98
repository = "https://github.com/microsoft/windows-rs"
109
readme = "readme.md"
1110

@@ -16,21 +15,5 @@ workspace = true
1615
default-target = "x86_64-pc-windows-msvc"
1716
targets = []
1817

19-
[features]
20-
default = ["metadata"]
21-
metadata = []
22-
2318
[dependencies]
24-
windows-metadata = { path = "../metadata", version = "0.58.0" }
2519
rayon = "1.7"
26-
27-
[dependencies.proc-macro2]
28-
version = "1.0"
29-
features = ["span-locations"]
30-
31-
[dependencies.serde]
32-
version = "1.0"
33-
features = ["derive"]
34-
35-
[dependencies.serde_json]
36-
version = "1.0"

crates/libs/bindgen/src/args.rs

Lines changed: 0 additions & 43 deletions
This file was deleted.

crates/libs/bindgen/src/derive.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use super::*;
2+
3+
pub struct Derive(HashMap<TypeName, Vec<String>>);
4+
5+
impl Derive {
6+
pub fn new(reader: &Reader, types: &TypeMap, derive: &[&str]) -> Self {
7+
let mut map = HashMap::new();
8+
9+
for derive in derive {
10+
let Some((name, derive)) = derive.split_once('=') else {
11+
panic!("`--derive` must be `<type name>=Comma,Separated,List");
12+
};
13+
14+
let tn = get_type_name(reader, name);
15+
16+
if !types.contains_key(&tn) {
17+
panic!("type not included: `{name}`");
18+
}
19+
20+
let derive = derive
21+
.split(',')
22+
.filter(|&derive| (!derive.is_empty()))
23+
.map(|derive| derive.to_string())
24+
.collect();
25+
map.insert(tn, derive);
26+
}
27+
28+
Self(map)
29+
}
30+
31+
pub fn get(&self, type_name: TypeName) -> impl Iterator<Item = String> + '_ {
32+
self.0.get(&type_name).into_iter().flatten().cloned()
33+
}
34+
}
35+
36+
fn get_type_name(reader: &Reader, path: &str) -> TypeName {
37+
if let Some((namespace, name)) = path.rsplit_once('.') {
38+
if let Some((namespace, types)) = reader.get_key_value(namespace) {
39+
if let Some((name, _)) = types.get_key_value(name) {
40+
return TypeName(namespace, name);
41+
}
42+
}
43+
} else {
44+
for (namespace, types) in reader.iter() {
45+
if let Some((name, _)) = types.get_key_value(path) {
46+
return TypeName(namespace, name);
47+
}
48+
}
49+
}
50+
51+
panic!("type not found: `{path}`");
52+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use super::*;
2+
3+
pub struct DeriveWriter(BTreeSet<String>);
4+
5+
impl DeriveWriter {
6+
pub fn new(writer: &Writer, type_name: TypeName) -> Self {
7+
let mut derive = BTreeSet::new();
8+
derive.extend(writer.config.derive.get(type_name));
9+
Self(derive)
10+
}
11+
12+
pub fn extend<I, S>(&mut self, iter: I)
13+
where
14+
I: IntoIterator<Item = S>,
15+
S: AsRef<str> + ToString,
16+
{
17+
self.0.extend(iter.into_iter().map(|s| s.to_string()));
18+
}
19+
}
20+
21+
impl ToTokens for DeriveWriter {
22+
fn to_tokens(&self, tokens: &mut TokenStream) {
23+
if !self.0.is_empty() {
24+
let derive = self.0.iter().map(|derive| to_ident(derive));
25+
tokens.combine(quote! {
26+
#[derive(#(#derive),*)]
27+
})
28+
}
29+
}
30+
}

crates/libs/bindgen/src/error.rs

Lines changed: 0 additions & 35 deletions
This file was deleted.

crates/libs/bindgen/src/filter.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use super::*;
2+
3+
#[derive(Debug, Default)]
4+
pub struct Filter(Vec<(String, bool)>);
5+
6+
impl Filter {
7+
pub fn new(reader: &Reader, include: &[&str], exclude: &[&str]) -> Self {
8+
let mut rules = vec![];
9+
10+
for filter in include {
11+
push_filter(reader, &mut rules, filter, true);
12+
}
13+
14+
for filter in exclude {
15+
push_filter(reader, &mut rules, filter, false)
16+
}
17+
18+
debug_assert!(!rules.is_empty());
19+
20+
rules.sort_unstable_by(|left, right| {
21+
let left = (left.0.len(), !left.1);
22+
let right = (right.0.len(), !right.1);
23+
left.cmp(&right).reverse()
24+
});
25+
26+
Self(rules)
27+
}
28+
29+
pub fn includes_namespace(&self, namespace: &str) -> bool {
30+
for rule in &self.0 {
31+
if rule.1 {
32+
// include
33+
if namespace_starts_with(&rule.0, namespace) {
34+
return true;
35+
}
36+
if namespace_starts_with(namespace, &rule.0) {
37+
return true;
38+
}
39+
} else {
40+
// exclude
41+
if namespace_starts_with(namespace, &rule.0) {
42+
return false;
43+
}
44+
}
45+
}
46+
47+
false
48+
}
49+
50+
pub fn includes_type_name(&self, name: TypeName) -> bool {
51+
for rule in &self.0 {
52+
if match_type_name(&rule.0, name.namespace(), name.name()) {
53+
return rule.1;
54+
}
55+
}
56+
57+
false
58+
}
59+
60+
pub fn excludes_type_name(&self, name: TypeName) -> bool {
61+
for rule in &self.0 {
62+
if match_type_name(&rule.0, name.namespace(), name.name()) {
63+
return !rule.1;
64+
}
65+
}
66+
67+
false
68+
}
69+
}
70+
71+
fn push_filter(reader: &Reader, rules: &mut Vec<(String, bool)>, filter: &str, include: bool) {
72+
if reader.contains_key(filter) {
73+
rules.push((filter.to_string(), include));
74+
return;
75+
}
76+
77+
if let Some((namespace, name)) = filter.rsplit_once('.') {
78+
if reader.with_full_name(namespace, name).next().is_some() {
79+
rules.push((filter.to_string(), include));
80+
return;
81+
}
82+
}
83+
84+
let mut pushed = false;
85+
86+
for (namespace, types) in reader.iter() {
87+
if types.get(filter).is_some() {
88+
rules.push((format!("{namespace}.{filter}"), include));
89+
pushed = true;
90+
}
91+
}
92+
93+
if pushed {
94+
return;
95+
}
96+
97+
if reader
98+
.keys()
99+
.any(|namespace| namespace_starts_with(namespace, filter))
100+
{
101+
rules.push((filter.to_string(), include));
102+
return;
103+
}
104+
105+
panic!("type not found: `{filter}`");
106+
}
107+
108+
fn match_type_name(rule: &str, namespace: &str, name: &str) -> bool {
109+
if rule.len() <= namespace.len() {
110+
return namespace.starts_with(rule);
111+
}
112+
113+
if !rule.starts_with(namespace) {
114+
return false;
115+
}
116+
117+
if rule.as_bytes()[namespace.len()] != b'.' {
118+
return false;
119+
}
120+
121+
name == &rule[namespace.len() + 1..]
122+
}

crates/libs/bindgen/src/guid.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
pub struct GUID(
2+
pub u32,
3+
pub u16,
4+
pub u16,
5+
pub u8,
6+
pub u8,
7+
pub u8,
8+
pub u8,
9+
pub u8,
10+
pub u8,
11+
pub u8,
12+
pub u8,
13+
);
14+
15+
impl std::fmt::Display for GUID {
16+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17+
write!(
18+
f,
19+
"{:08x?}-{:04x?}-{:04x?}-{:02x?}{:02x?}-{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}",
20+
self.0, self.1, self.2, self.3, self.4, self.5, self.6, self.7, self.8, self.9, self.10
21+
)
22+
}
23+
}

crates/libs/bindgen/src/io.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::io::BufRead;
2+
3+
pub fn read_file_lines(path: &str) -> Vec<String> {
4+
let file = std::io::BufReader::new(
5+
std::fs::File::open(path).unwrap_or_else(|_| panic!("failed to open file `{path}`")),
6+
);
7+
8+
file.lines()
9+
.map(|line| line.unwrap_or_else(|_| panic!("failed to read file lines `{path}`")))
10+
.collect()
11+
}
12+
13+
pub fn write_to_file<C: AsRef<[u8]>>(path: &str, contents: C) {
14+
if let Some(parent) = std::path::Path::new(path).parent() {
15+
std::fs::create_dir_all(parent)
16+
.unwrap_or_else(|_| panic!("failed to create directory `{path}`"));
17+
}
18+
19+
std::fs::write(path, contents).unwrap_or_else(|_| panic!("failed to write file `{path}`"));
20+
}

0 commit comments

Comments
 (0)