Skip to content

Commit

Permalink
features
Browse files Browse the repository at this point in the history
  • Loading branch information
riverar committed Feb 5, 2024
1 parent 5c5c82a commit ada585c
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 5 deletions.
6 changes: 4 additions & 2 deletions crates/libs/bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ mod args;
mod error;
mod metadata;
mod rdl;
mod rust;
#[doc(hidden)]
pub mod rust;
mod tokens;
mod tree;
mod winmd;
Expand Down Expand Up @@ -160,7 +161,8 @@ fn filter_input(input: &[&str], extensions: &[&str]) -> Result<Vec<String>> {
Ok(results)
}

fn read_input(input: &[&str]) -> Result<Vec<metadata::File>> {
#[doc(hidden)]
pub fn read_input(input: &[&str]) -> Result<Vec<metadata::File>> {
let input = filter_input(input, &["winmd", "rdl"])?;
let mut results = vec![];

Expand Down
7 changes: 4 additions & 3 deletions crates/libs/bindgen/src/rust/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod cfg;
#[doc(hidden)]
pub mod cfg;
mod classes;
mod com_methods;
mod constants;
Expand All @@ -18,8 +19,9 @@ mod winrt_methods;
mod writer;
use super::*;
use crate::{Error, Result, Tree};
use cfg::*;
pub use cfg::*;
use rayon::prelude::*;
pub 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 @@ -135,7 +137,6 @@ use method_names::*;
use std::collections::*;
use std::fmt::Write;
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 @@ -1155,6 +1155,22 @@ fn const_ptrs(pointers: usize) -> TokenStream {
"*const ".repeat(pointers).into()
}

pub fn cfg_features(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
33 changes: 33 additions & 0 deletions crates/tools/features/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "tool_features"
version = "0.1.0"
authors = ["Microsoft"]
edition = "2021"
rust-version = "1.56"
license = "MIT OR Apache-2.0"
description = "Windows cargo feature search tool"
repository = "https://github.com/microsoft/windows-rs"
readme = "readme.md"

[dependencies.indexmap]
version = "2.1.0"
features = ["serde"]

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

[dependencies.serde_json]
version = "1.0"

[dependencies.windows]
path = "../../libs/windows"
version = "0.52.0"

[dependencies.windows-bindgen]
path = "../../libs/bindgen"
version = "0.52.0"

[dependencies.windows-metadata]
path = "../../libs/metadata"
version = "0.52.0"
136 changes: 136 additions & 0 deletions crates/tools/features/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use indexmap::IndexMap;
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};
use std::{fs::OpenOptions, io::Write};
use windows_metadata::Item;

fn main() {
match feature_index() {
Ok(ok) => {
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open("index.json")
.unwrap()
.write_all(ok.as_bytes())
.expect("Failed to write out index.");
}
Err(error) => {
eprintln!("{}", error);
std::process::exit(1);
}
}
}

#[derive(Default, Serialize)]
struct FeatureIndex {
#[serde(serialize_with = "serialize_keys")]
namespace_map: IndexMap<String, u32>,
#[serde(serialize_with = "serialize_keys")]
feature_map: IndexMap<String, u32>,
namespaces: IndexMap<u32, Vec<FeatureIndexItem>>,
}

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

fn serialize_keys<S>(map: &IndexMap<String, u32>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(map.len()))?;
for (k, _v) in map {
seq.serialize_element(k)?;
}
seq.end()
}

pub fn feature_index() -> windows::core::Result<String> {
let files = windows_bindgen::read_input(&[]).unwrap();
let reader = windows_metadata::Reader::filter(
files,
&["Windows"],
&[
"Windows.AI.MachineLearning.Preview",
"Windows.ApplicationModel.SocialInfo",
"Windows.Devices.AllJoyn",
"Windows.Devices.Perception",
"Windows.Security.Authentication.Identity.Provider",
"Windows.Services.Cortana",
"Windows.System.Power.Diagnostics",
"Windows.System.Preview",
"Windows.UI.Xaml",
"Windows.Win32.Foundation.Metadata",
"Windows.Win32.System.Diagnostics.Debug.WebApp",
"Windows.Win32.System.WinRT.Xaml",
"Windows.Win32.UI.Xaml",
"Windows.Win32.Web.MsHtml",
],
);

let mut feature_index = FeatureIndex {
..Default::default()
};
let mut next_ns_idx = 0;
let mut next_feature_idx = 0;

for namespace in reader.namespaces() {
for item in reader.namespace_items(namespace) {
let namespace_idx = feature_index
.namespace_map
.entry(namespace.to_string())
.or_insert_with(|| {
next_ns_idx += 1;
next_ns_idx
});

let mut index_item = FeatureIndexItem {
..Default::default()
};
let mut cfg = windows_bindgen::rust::Cfg::default();
cfg.add_feature(namespace);

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

let cfg_features = windows_bindgen::rust::cfg_features(&cfg);
index_item.features = cfg_features
.iter()
.map(|feature| {
let feature_idx = feature_index
.feature_map
.entry(feature.clone())
.or_insert_with(|| {
next_feature_idx += 1;
next_feature_idx
});
*feature_idx
})
.collect();

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

Ok(serde_json::to_string(&feature_index).unwrap())
}

0 comments on commit ada585c

Please sign in to comment.