Skip to content

Commit

Permalink
Generate features index for windows and sys crates (#2859)
Browse files Browse the repository at this point in the history
  • Loading branch information
riverar authored Feb 20, 2024
1 parent e83513b commit 1c55102
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 3 deletions.
7 changes: 7 additions & 0 deletions crates/libs/bindgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,10 @@ features = ["full", "extra-traits"]
[dependencies.proc-macro2]
version = "1.0"
features = ["span-locations"]

[dependencies.serde]
version = "1.0.196"
features = ["derive"]

[dependencies.serde_json]
version = "1.0.113"
69 changes: 69 additions & 0 deletions crates/libs/bindgen/src/rust/index.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use super::*;
use rust::cfg::*;
use serde::Serialize;
use std::collections::BTreeMap;
use windows_metadata::Item;

#[derive(Default, Serialize)]
struct Index {
namespace_map: Vec<String>,
feature_map: Vec<String>,
namespaces: BTreeMap<usize, Vec<IndexItem>>,
}

#[derive(Default, Serialize)]
struct IndexItem {
name: String,
features: Vec<usize>,
}

pub fn gen_index(writer: &Writer) -> String {
let mut feature_index = Index { ..Default::default() };

for namespace in writer.reader.namespaces() {
let namespace_idx = match feature_index.namespace_map.iter().position(|ns| ns == namespace) {
Some(idx) => idx,
None => {
feature_index.namespace_map.push(namespace.to_string());
feature_index.namespace_map.len() - 1
}
};

for item in writer.reader.namespace_items(namespace) {
let mut index_item = IndexItem { ..Default::default() };
let mut cfg = Cfg::default();
cfg.add_feature(namespace);

cfg = match item {
Item::Type(def) => {
index_item.name = def.name().to_string();
cfg.union(&type_def_cfg(writer, def, &[]))
}
Item::Const(field) => {
index_item.name = field.name().to_string();
cfg.union(&field_cfg(writer, field))
}
Item::Fn(method, _) => {
index_item.name = method.name().to_string();
cfg.union(&signature_cfg(writer, method))
}
};

let cfg_features = cfg_features(&cfg);
index_item.features = cfg_features
.iter()
.map(|feature| match feature_index.feature_map.iter().position(|f| f == feature) {
Some(idx) => idx,
None => {
feature_index.feature_map.push(feature.to_string());
feature_index.feature_map.len() - 1
}
})
.collect();

feature_index.namespaces.entry(namespace_idx).or_default().push(index_item);
}
}

serde_json::to_string(&feature_index).unwrap()
}
11 changes: 8 additions & 3 deletions crates/libs/bindgen/src/rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod extensions;
mod functions;
mod handles;
mod implements;
mod index;
mod interfaces;
mod iterators;
mod method_names;
Expand All @@ -16,8 +17,11 @@ mod structs;
mod try_format;
mod winrt_methods;
mod writer;

use super::*;
use index::*;
use rayon::prelude::*;
use writer::*;

pub fn from_reader(reader: &'static metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
let mut writer = Writer::new(reader, output);
Expand Down Expand Up @@ -101,7 +105,8 @@ fn gen_package(writer: &Writer) -> Result<()> {
Ok::<(), Error>(())
})?;

let cargo_toml = format!("{}/Cargo.toml", super::directory(directory));
let package_root = super::directory(directory);
let cargo_toml = format!("{package_root}/Cargo.toml");
let mut toml = String::new();

for line in read_file_lines(&cargo_toml)? {
Expand Down Expand Up @@ -129,14 +134,14 @@ fn gen_package(writer: &Writer) -> Result<()> {
}
}

write_to_file(&cargo_toml, toml)
write_to_file(&cargo_toml, toml)?;
write_to_file(&format!("{package_root}/features.json"), gen_index(writer))
}

use method_names::*;
use std::fmt::Write;
use tokens::*;
use try_format::*;
use writer::*;

fn namespace(writer: &Writer, tree: &Tree) -> String {
let writer = &mut writer.clone();
Expand Down
16 changes: 16 additions & 0 deletions crates/libs/bindgen/src/rust/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,22 @@ fn const_ptrs(pointers: usize) -> TokenStream {
"*const ".repeat(pointers).into()
}

pub fn cfg_features(cfg: &cfg::Cfg) -> Vec<String> {
let mut compact = Vec::<&'static str>::new();
for feature in cfg.types.keys() {
if !feature.is_empty() {
for pos in 0..compact.len() {
if starts_with(feature, unsafe { compact.get_unchecked(pos) }) {
compact.remove(pos);
break;
}
}
compact.push(feature);
}
}
compact.into_iter().map(to_feature).collect()
}

fn to_feature(name: &str) -> String {
let mut feature = String::new();

Expand Down
1 change: 1 addition & 0 deletions crates/libs/sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description = "Rust for Windows"
repository = "https://github.com/microsoft/windows-rs"
readme = "readme.md"
categories = ["os::windows-apis"]
exclude = ["features.json"]

[lints]
workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/libs/sys/features.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crates/libs/windows/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ repository = "https://github.com/microsoft/windows-rs"
documentation = "https://microsoft.github.io/windows-docs-rs/"
readme = "readme.md"
categories = ["os::windows-apis"]
exclude = ["features.json"]

[lints]
workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/libs/windows/features.json

Large diffs are not rendered by default.

0 comments on commit 1c55102

Please sign in to comment.