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
use super::*;
pub fn crate_winmds() -> &'static [File] {
use std::{mem::MaybeUninit, sync::Once};
static ONCE: Once = Once::new();
static mut VALUE: MaybeUninit<Vec<File>> = MaybeUninit::uninit();
ONCE.call_once(|| {
unsafe { VALUE = MaybeUninit::new(get_crate_winmds()) }
});
unsafe { &*VALUE.as_ptr() }
}
fn cargo_metadata() -> &'static str {
use std::{mem::MaybeUninit, sync::Once};
static ONCE: Once = Once::new();
static mut VALUE: MaybeUninit<String> = MaybeUninit::uninit();
ONCE.call_once(|| {
let output = std::process::Command::new(env!("CARGO"))
.arg("metadata")
.arg("--format-version=1")
.arg("--no-deps")
.arg("--offline")
.output()
.expect("Failed to run `cargo metadata`");
unsafe {
VALUE = MaybeUninit::new(
String::from_utf8(output.stdout).expect("Cargo metadata is not utf-8"),
)
}
});
unsafe { &*VALUE.as_ptr() }
}
pub fn workspace_dir() -> String {
const JSON_KEY: &str = r#""workspace_root":"#;
let json = cargo_metadata();
let beginning_index = json
.rfind(JSON_KEY)
.expect("Cargo metadata did not contain `workspace_root` key.")
+ JSON_KEY.len()
+ 1;
let ending_index = json[beginning_index..]
.find('"')
.expect("Cargo metadata ended before closing '\"' in `workspace_root` value");
json[beginning_index..beginning_index + ending_index].replace("\\\\", "\\")
}
pub fn target_dir() -> String {
const JSON_KEY: &str = r#""target_directory":"#;
let json = cargo_metadata();
let beginning_index = json
.rfind(JSON_KEY)
.expect("Cargo metadata did not contain `target_directory` key.")
+ JSON_KEY.len()
+ 1;
let ending_index = json[beginning_index..]
.find('"')
.expect("Cargo metadata ended before closing '\"' in `target_directory` value");
json[beginning_index..beginning_index + ending_index].replace("\\\\", "\\")
}
fn get_crate_winmds() -> Vec<File> {
fn push_dir(result: &mut Vec<File>, dir: &std::path::Path) {
if let Ok(files) = std::fs::read_dir(&dir) {
for file in files.filter_map(|file| file.ok()) {
if let Ok(file_type) = file.file_type() {
if file_type.is_file() {
let path = file.path();
if let Some("winmd") =
path.extension().and_then(|extension| extension.to_str())
{
result.push(File::new(path));
}
}
}
}
}
}
let mut result = vec![];
if let Ok(dir) = std::env::var("CARGO_MANIFEST_DIR") {
let mut dir: std::path::PathBuf = dir.into();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);
}
let dir = std::env::var("PATH").expect("No `PATH` env variable set");
let end = dir.find(';').expect("Path not ending in `;`");
let mut dir: std::path::PathBuf = dir[..end].into();
dir.pop();
dir.pop();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);
let mut dir: std::path::PathBuf = target_dir().into();
dir.push(".windows");
dir.push("winmd");
push_dir(&mut result, &dir);
result
}