summaryrefslogtreecommitdiffstats
path: root/vendor/windows-metadata
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/windows-metadata
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/windows-metadata')
-rw-r--r--vendor/windows-metadata/.cargo-checksum.json2
-rw-r--r--vendor/windows-metadata/Cargo.toml4
-rw-r--r--vendor/windows-metadata/readme.md37
-rw-r--r--vendor/windows-metadata/src/attributes.rs2
-rw-r--r--vendor/windows-metadata/src/bindings.rs (renamed from vendor/windows-metadata/src/imp/bindings.rs)2
-rw-r--r--vendor/windows-metadata/src/blob.rs14
-rw-r--r--vendor/windows-metadata/src/codes.rs216
-rw-r--r--vendor/windows-metadata/src/column.rs11
-rw-r--r--vendor/windows-metadata/src/file.rs (renamed from vendor/windows-metadata/src/file/mod.rs)117
-rw-r--r--vendor/windows-metadata/src/file/reader.rs359
-rw-r--r--vendor/windows-metadata/src/file/view.rs55
-rw-r--r--vendor/windows-metadata/src/filter.rs43
-rw-r--r--vendor/windows-metadata/src/guid.rs40
-rw-r--r--vendor/windows-metadata/src/imp/mod.rs46
-rw-r--r--vendor/windows-metadata/src/lib.rs488
-rw-r--r--vendor/windows-metadata/src/reader.rs255
-rw-r--r--vendor/windows-metadata/src/row.rs164
-rw-r--r--vendor/windows-metadata/src/table.rs (renamed from vendor/windows-metadata/src/file/table.rs)14
-rw-r--r--vendor/windows-metadata/src/tables.rs420
-rw-r--r--vendor/windows-metadata/src/type.rs33
-rw-r--r--vendor/windows-metadata/src/type_name.rs21
21 files changed, 1139 insertions, 1204 deletions
diff --git a/vendor/windows-metadata/.cargo-checksum.json b/vendor/windows-metadata/.cargo-checksum.json
index 3055b9947..42d3edbcf 100644
--- a/vendor/windows-metadata/.cargo-checksum.json
+++ b/vendor/windows-metadata/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c62bdf1f7590fca80f0bce1d57e44f066c061ab0af56869c5d1b0e354745b245","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","src/attributes.rs":"82fef5cd2f08624864139b9a3aef592ae2730c5cf185b06164b8db05314e81f3","src/blob.rs":"398f86e96c9bc5c35d3f2d0188e9183088b01f87d40f50fded1eceb3c4397723","src/codes.rs":"dd1a37c7417073c7f4d8682d0da4e5c3ac8897a8e92d902c0940658a26090603","src/file/mod.rs":"2b606c0216f82309e07c03d5a90dc2742a2aba6c5a9bdb4c0452c6ef9aaac3c7","src/file/reader.rs":"450a7c0935bb2089ce63abfa1fdb6f4827ea15a9b297b31baebe7f324998713a","src/file/table.rs":"906f304d744ec4d030160cdb25ba1c4e35965d38d77ff514db17ca760cdc7c58","src/file/view.rs":"def9bed45a3a6f12b501409b204d165ad5f8231359fc783cfcee9eaf1160bd59","src/filter.rs":"b6e77d22c996786af05287a562b8c4fe90f98a3ed2a180ad5f9854a4b68a0556","src/guid.rs":"069c5aa795b0858a012fe67f0fb8e5a4b1be17e1087283562ab51e68108a0e59","src/imp/bindings.rs":"c6fb2efdfb1ea133e47178a1de71c314021319e754ccf86a4639e6ce01920eab","src/imp/mod.rs":"7964e480c9a32a97735364b6386aa3d3b0ea5071c1ff43e6f8eaa786b49219f0","src/lib.rs":"4e2db9f8b2915f271bc4f3472fe497ad8467db56822262a7411c51f602b03f52","src/row.rs":"391b645ee0c7f034458c4fe49579bc1b60caf8d93c3b683ac96c1c7da2f2a9ab","src/type.rs":"920c260b597ef87984ebb3504134d6e915af7c4c6242fc50c0dd38e7d173df56","src/type_name.rs":"8414f7916932b7ed2a8d2a1cd48c14ad0c89c6d832fff5d5572734e1335131a6"},"package":"753135d996f9da437c0b31dbde3032489a61708361929bcc07d4fba0b161000e"} \ No newline at end of file
+{"files":{"Cargo.toml":"47ea9510176bee8b9ab0e08cc5dcf090b1f4aea4dbd1e7922a512022382826d7","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"c413987d2515509f71dc3f1f10362152b5ccd822d74896db1a3af152eae3b56a","src/attributes.rs":"64b6d61062a87a3df4b6c770e64f95f50a5d25a674caacc59474d21f60a8ed55","src/bindings.rs":"b8584035f0b26bbe4df8b9c5929b194eb895c7f02b7a03f60b36c82a873fc2f0","src/blob.rs":"c8505ed1164ca045fc95c75b07872ac81c7167b79ab3dc189de6ab67a852db66","src/codes.rs":"d778f8be69e28f403a3a5547e906d1228d11285269cc022d20544527619f27e4","src/column.rs":"95102b26fefd96a2c5ca1ec872a00ffdc9a774a90be1894a6b4320dbd90cd42b","src/file.rs":"cb210eba5a25b8fd7de388e955114c99a39a8cb6b9b2c35057744f3518ebf5d9","src/filter.rs":"1e94b3aa362954cb4c5cde344aa0b7ff58d56f2503d9df2f688587df9aeaf3d2","src/lib.rs":"efa0097044dbd950ef8ee2aad9679363decd8e2ec4ec9ea0617a27772648e6e2","src/reader.rs":"2d00969480a2517fa6e58a88a52c67b42c134376aa52a0f72ade9ed87c99190c","src/row.rs":"9cdbfe20a393f2c914e24adec4dc0fca91034f1998ec6478c0695fba84c86631","src/table.rs":"49021863fca609969ddf57816a0a3dd5f4b3b8c12eec6d5d8ece1d0fa9829dff","src/tables.rs":"14511b2b29b43df3963a83485373c06055825f1cb6e1ebac3bac34f04142bcf4","src/type.rs":"f1c71a8ccbd5fdfe3179b500873012e163ea968a87d371ff03a6d736f5275aad","src/type_name.rs":"1f37e1feffd83ed94775571f3bac0156f63673120737dab8b30495b483007137"},"package":"218fd59201e26acdbb894fa2b302d1de84bf3eec7d0eb894ac8e9c5a854ee4ef"} \ No newline at end of file
diff --git a/vendor/windows-metadata/Cargo.toml b/vendor/windows-metadata/Cargo.toml
index e220f63d1..358588b84 100644
--- a/vendor/windows-metadata/Cargo.toml
+++ b/vendor/windows-metadata/Cargo.toml
@@ -11,10 +11,12 @@
[package]
edition = "2021"
+rust-version = "1.64"
name = "windows-metadata"
-version = "0.51.1"
+version = "0.52.0"
authors = ["Microsoft"]
description = "Windows metadata reader"
+readme = "readme.md"
license = "MIT OR Apache-2.0"
repository = "https://github.com/microsoft/windows-rs"
diff --git a/vendor/windows-metadata/readme.md b/vendor/windows-metadata/readme.md
new file mode 100644
index 000000000..e7960bdd0
--- /dev/null
+++ b/vendor/windows-metadata/readme.md
@@ -0,0 +1,37 @@
+## Windows metadata reader
+
+The [windows-metadata](https://crates.io/crates/windows-metadata) crate provides a fast reader for Windows metadata files based on the ECMA-335 file format.
+
+* [Getting started](https://kennykerr.ca/rust-getting-started/)
+* [Samples](https://github.com/microsoft/windows-rs/tree/0.52.0/crates/samples) <!-- link to samples for upcoming release -->
+* [Releases](https://github.com/microsoft/windows-rs/releases)
+
+Start by adding the following to your Cargo.toml file:
+
+```toml
+[dependencies.windows-metadata]
+version = "0.52"
+```
+
+Read metadata as needed:
+
+```rust,no_run
+use windows_metadata::*;
+
+fn main() {
+ let bytes = std::fs::read(r#"C:\Windows\System32\WinMetadata\Windows.Foundation.winmd"#)
+ .expect("File not found");
+
+ let file = File::new(bytes).expect("Invalid metadata");
+
+ let reader = Reader::new(vec![file]);
+
+ for def in reader.get_type_def("Windows.Foundation", "IAsyncInfo") {
+ println!("{}", def.name());
+
+ for method in def.methods() {
+ println!("{}", method.name());
+ }
+ }
+}
+```
diff --git a/vendor/windows-metadata/src/attributes.rs b/vendor/windows-metadata/src/attributes.rs
index 789214739..1bc2922da 100644
--- a/vendor/windows-metadata/src/attributes.rs
+++ b/vendor/windows-metadata/src/attributes.rs
@@ -2,7 +2,7 @@
macro_rules! flags {
($name:ident, $size:ty) => {
- #[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
+ #[derive(Default, Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd)]
pub struct $name(pub $size);
impl $name {
pub fn contains(&self, contains: Self) -> bool {
diff --git a/vendor/windows-metadata/src/imp/bindings.rs b/vendor/windows-metadata/src/bindings.rs
index abaebdd02..9f92aec78 100644
--- a/vendor/windows-metadata/src/imp/bindings.rs
+++ b/vendor/windows-metadata/src/bindings.rs
@@ -1,4 +1,4 @@
-// Bindings generated by `windows-bindgen` 0.51.1
+// Bindings generated by `windows-bindgen` 0.52.0
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
pub type CorElementType = u8;
diff --git a/vendor/windows-metadata/src/blob.rs b/vendor/windows-metadata/src/blob.rs
index a54336db1..398d5fb3b 100644
--- a/vendor/windows-metadata/src/blob.rs
+++ b/vendor/windows-metadata/src/blob.rs
@@ -1,11 +1,11 @@
use super::*;
-pub struct Blob<'a> {
- pub file: usize,
- pub slice: &'a [u8],
+pub struct Blob {
+ pub file: &'static File,
+ pub slice: &'static [u8],
}
-impl<'a> std::ops::Deref for Blob<'a> {
+impl std::ops::Deref for Blob {
type Target = [u8];
fn deref(&self) -> &[u8] {
@@ -13,8 +13,8 @@ impl<'a> std::ops::Deref for Blob<'a> {
}
}
-impl<'a> Blob<'a> {
- pub fn new(file: usize, slice: &'a [u8]) -> Self {
+impl Blob {
+ pub fn new(file: &'static File, slice: &'static [u8]) -> Self {
Self { file, slice }
}
@@ -58,7 +58,7 @@ impl<'a> Blob<'a> {
mods
}
- pub fn read_str(&mut self) -> &str {
+ pub fn read_str(&mut self) -> &'static str {
let len = self.read_usize();
let value = unsafe { std::str::from_utf8_unchecked(&self.slice[..len]) };
self.offset(len);
diff --git a/vendor/windows-metadata/src/codes.rs b/vendor/windows-metadata/src/codes.rs
index d19f6e476..3171cb528 100644
--- a/vendor/windows-metadata/src/codes.rs
+++ b/vendor/windows-metadata/src/codes.rs
@@ -1,183 +1,91 @@
use super::*;
pub trait Decode {
- fn decode(file: usize, code: usize) -> Self;
+ fn decode(file: &'static File, code: usize) -> Self;
}
-pub enum AttributeType {
- MemberRef(MemberRef),
-}
-
-impl Decode for AttributeType {
- fn decode(file: usize, code: usize) -> Self {
- let (kind, row) = (code & ((1 << 3) - 1), (code >> 3) - 1);
- match kind {
- 3 => Self::MemberRef(MemberRef(Row::new(row, file))),
- rest => unimplemented!("{rest:?}"),
+macro_rules! code {
+ ($name:ident($size:literal) $(($table:ident, $code:literal))+) => {
+ #[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
+ pub enum $name {
+ $($table($table),)*
}
- }
-}
-
-pub enum HasAttribute {
- MethodDef(MethodDef),
- Field(Field),
- TypeRef(TypeRef),
- TypeDef(TypeDef),
- Param(Param),
- InterfaceImpl(InterfaceImpl),
- MemberRef(MemberRef),
- TypeSpec(TypeSpec),
- GenericParam(GenericParam),
-}
-
-impl HasAttribute {
- pub fn encode(&self) -> usize {
- match self {
- Self::MethodDef(row) => (row.0.row + 1) << 5,
- Self::Field(row) => ((row.0.row + 1) << 5) | 1,
- Self::TypeRef(row) => ((row.0.row + 1) << 5) | 2,
- Self::TypeDef(row) => ((row.0.row + 1) << 5) | 3,
- Self::Param(row) => ((row.0.row + 1) << 5) | 4,
- Self::InterfaceImpl(row) => ((row.0.row + 1) << 5) | 5,
- Self::MemberRef(row) => ((row.0.row + 1) << 5) | 6,
- Self::TypeSpec(row) => ((row.0.row + 1) << 5) | 13,
- Self::GenericParam(row) => ((row.0.row + 1) << 5) | 19,
+ impl Decode for $name {
+ fn decode(file: &'static File, code: usize) -> Self {
+ let (kind, row) = (code & ((1 << $size) - 1), (code >> $size) - 1);
+ match kind {
+ $($code => Self::$table($table(Row::new(file, row))),)*
+ rest => unimplemented!("{rest:?}"),
+ }
+ }
}
- }
-}
-
-impl From<MethodDef> for HasAttribute {
- fn from(from: MethodDef) -> Self {
- Self::MethodDef(from)
- }
-}
-impl From<Field> for HasAttribute {
- fn from(from: Field) -> Self {
- Self::Field(from)
- }
-}
-impl From<TypeRef> for HasAttribute {
- fn from(from: TypeRef) -> Self {
- Self::TypeRef(from)
- }
-}
-impl From<TypeDef> for HasAttribute {
- fn from(from: TypeDef) -> Self {
- Self::TypeDef(from)
- }
-}
-impl From<Param> for HasAttribute {
- fn from(from: Param) -> Self {
- Self::Param(from)
- }
-}
-impl From<InterfaceImpl> for HasAttribute {
- fn from(from: InterfaceImpl) -> Self {
- Self::InterfaceImpl(from)
- }
-}
-impl From<MemberRef> for HasAttribute {
- fn from(from: MemberRef) -> Self {
- Self::MemberRef(from)
- }
-}
-impl From<TypeSpec> for HasAttribute {
- fn from(from: TypeSpec) -> Self {
- Self::TypeSpec(from)
- }
-}
-impl From<GenericParam> for HasAttribute {
- fn from(from: GenericParam) -> Self {
- Self::GenericParam(from)
- }
-}
-
-#[derive(Clone)]
-pub enum HasConstant {
- Field(Field),
-}
-
-impl HasConstant {
- pub fn encode(&self) -> usize {
- match self {
- Self::Field(row) => (row.0.row + 1) << 2,
+ impl $name {
+ pub fn encode(&self) -> usize {
+ match self {
+ $(Self::$table(row) => (row.index() + 1) << $size | $code,)*
+ }
+ }
}
- }
+ $(
+ impl From<$table> for $name {
+ fn from(from: $table) -> Self {
+ Self::$table(from)
+ }
+ }
+ )*
+ };
}
-#[derive(Clone)]
-pub enum MemberForwarded {
- MethodDef(MethodDef),
+code! { AttributeType(3)
+ (MemberRef, 3)
}
-impl MemberForwarded {
- pub fn encode(&self) -> usize {
- match self {
- Self::MethodDef(value) => ((value.0.row + 1) << 1) | 1,
- }
- }
+code! { HasAttribute(5)
+ (MethodDef, 0)
+ (Field, 1)
+ (TypeRef, 2)
+ (TypeDef, 3)
+ (Param, 4)
+ (InterfaceImpl, 5)
+ (MemberRef, 6)
+ (TypeSpec, 13)
+ (GenericParam, 19)
}
-pub enum MemberRefParent {
- TypeRef(TypeRef),
+code! { HasConstant(2)
+ (Field, 0)
}
-impl Decode for MemberRefParent {
- fn decode(file: usize, code: usize) -> Self {
- let (kind, row) = (code & ((1 << 3) - 1), (code >> 3) - 1);
- match kind {
- 1 => Self::TypeRef(TypeRef(Row::new(row, file))),
- rest => unimplemented!("{rest:?}"),
- }
- }
+code! { MemberForwarded(1)
+ (MethodDef, 1)
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
-pub enum TypeDefOrRef {
- TypeDef(TypeDef),
- TypeRef(TypeRef),
- TypeSpec(TypeSpec),
-}
-
-impl Decode for TypeDefOrRef {
- fn decode(file: usize, code: usize) -> Self {
- let (kind, row) = (code & ((1 << 2) - 1), (code >> 2) - 1);
- match kind {
- 0 => Self::TypeDef(TypeDef(Row::new(row, file))),
- 1 => Self::TypeRef(TypeRef(Row::new(row, file))),
- 2 => Self::TypeSpec(TypeSpec(Row::new(row, file))),
- rest => unimplemented!("{rest:?}"),
- }
- }
+code! { MemberRefParent(3)
+ (TypeRef, 1)
}
-pub enum TypeOrMethodDef {
- TypeDef(TypeDef),
+code! { TypeDefOrRef(2)
+ (TypeDef, 0)
+ (TypeRef, 1)
+ (TypeSpec, 2)
}
-impl TypeOrMethodDef {
- pub fn encode(&self) -> usize {
- match self {
- Self::TypeDef(value) => (value.0.row + 1) << 1,
- }
- }
+code! { TypeOrMethodDef(1)
+ (TypeDef, 0)
}
-pub enum ResolutionScope {
- Module(Module),
- ModuleRef(ModuleRef),
- AssemblyRef(AssemblyRef),
- TypeRef(TypeRef),
+code! { ResolutionScope(2)
+ (Module, 0)
+ (ModuleRef, 1)
+ (AssemblyRef, 2)
+ (TypeRef, 3)
}
-impl Decode for ResolutionScope {
- fn decode(file: usize, code: usize) -> Self {
- let (kind, row) = (code & ((1 << 2) - 1), (code >> 2) - 1);
- match kind {
- 0 => Self::Module(Module(Row::new(row, file))),
- 1 => Self::ModuleRef(ModuleRef(Row::new(row, file))),
- 2 => Self::AssemblyRef(AssemblyRef(Row::new(row, file))),
- 3 => Self::TypeRef(TypeRef(Row::new(row, file))),
+impl TypeDefOrRef {
+ pub fn type_name(&self) -> TypeName {
+ match self {
+ Self::TypeDef(row) => row.type_name(),
+ Self::TypeRef(row) => row.type_name(),
rest => unimplemented!("{rest:?}"),
}
}
diff --git a/vendor/windows-metadata/src/column.rs b/vendor/windows-metadata/src/column.rs
new file mode 100644
index 000000000..9a678daa8
--- /dev/null
+++ b/vendor/windows-metadata/src/column.rs
@@ -0,0 +1,11 @@
+#[derive(Default)]
+pub struct Column {
+ pub offset: usize,
+ pub width: usize,
+}
+
+impl Column {
+ pub fn new(offset: usize, width: usize) -> Self {
+ Self { offset, width }
+ }
+}
diff --git a/vendor/windows-metadata/src/file/mod.rs b/vendor/windows-metadata/src/file.rs
index 41a6db920..e8867c1c9 100644
--- a/vendor/windows-metadata/src/file/mod.rs
+++ b/vendor/windows-metadata/src/file.rs
@@ -1,28 +1,55 @@
-mod reader;
-mod table;
-mod view;
use super::*;
-pub use reader::RowReader;
-use std::cmp::Ordering;
-use table::Table;
-use view::View;
type Result<T> = std::result::Result<T, ()>;
-#[derive(Default)]
pub struct File {
- bytes: Vec<u8>,
- strings: usize,
- blobs: usize,
- tables: [Table; 17],
+ pub reader: *const Reader,
+ pub bytes: Vec<u8>,
+ pub strings: usize,
+ pub blobs: usize,
+ pub tables: [Table; 17],
}
+impl std::fmt::Debug for File {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::write!(f, "{:?}", self.bytes.as_ptr())
+ }
+}
+
+impl std::hash::Hash for File {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.bytes.as_ptr().hash(state);
+ }
+}
+
+impl PartialEq for File {
+ fn eq(&self, other: &Self) -> bool {
+ self.bytes.as_ptr() == other.bytes.as_ptr()
+ }
+}
+
+impl Eq for File {}
+
+impl Ord for File {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.bytes.as_ptr().cmp(&other.bytes.as_ptr())
+ }
+}
+
+impl PartialOrd for File {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+unsafe impl Sync for File {}
+
impl File {
pub fn new(bytes: Vec<u8>) -> Option<Self> {
Self::ok(bytes).ok()
}
fn ok(bytes: Vec<u8>) -> Result<Self> {
- let mut result = File { bytes, ..Default::default() };
+ let mut result = File { bytes, reader: std::ptr::null(), strings: 0, blobs: 0, tables: Default::default() };
let dos = result.bytes.view_as::<IMAGE_DOS_HEADER>(0)?;
@@ -282,7 +309,7 @@ impl File {
Ok(result)
}
- fn usize(&self, row: usize, table: usize, column: usize) -> usize {
+ pub fn usize(&self, row: usize, table: usize, column: usize) -> usize {
let table = &self.tables[table];
let column = &table.columns[column];
let offset = table.offset + row * table.width + column.offset;
@@ -294,7 +321,7 @@ impl File {
}
}
- fn lower_bound_of(&self, table: usize, mut first: usize, last: usize, column: usize, value: usize) -> usize {
+ pub fn lower_bound_of(&self, table: usize, mut first: usize, last: usize, column: usize, value: usize) -> usize {
let mut count = last - first;
while count > 0 {
let count2 = count / 2;
@@ -309,7 +336,7 @@ impl File {
first
}
- fn upper_bound_of(&self, table: usize, mut first: usize, last: usize, column: usize, value: usize) -> usize {
+ pub fn upper_bound_of(&self, table: usize, mut first: usize, last: usize, column: usize, value: usize) -> usize {
let mut count = last - first;
while count > 0 {
let count2 = count / 2;
@@ -324,8 +351,8 @@ impl File {
first
}
- pub fn table<R: AsRow>(&self, file: usize) -> RowIterator<R> {
- RowIterator::new(file, 0..self.tables[R::TABLE].len)
+ pub fn table<R: AsRow>(&'static self) -> RowIterator<R> {
+ RowIterator::new(self, 0..self.tables[R::TABLE].len)
}
}
@@ -336,3 +363,57 @@ fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Result<&IMAG
fn offset_from_rva(section: &IMAGE_SECTION_HEADER, rva: u32) -> usize {
(rva - section.VirtualAddress + section.PointerToRawData) as usize
}
+
+trait View {
+ fn view_as<T>(&self, offset: usize) -> Result<&T>;
+ fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Result<&[T]>;
+ fn copy_as<T: Copy>(&self, offset: usize) -> Result<T>;
+ fn view_as_str(&self, offset: usize) -> Result<&[u8]>;
+ fn is_proper_length<T>(&self, offset: usize) -> Result<()>;
+ fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Result<*const T>;
+}
+
+impl View for [u8] {
+ fn view_as<T>(&self, offset: usize) -> Result<&T> {
+ unsafe { Ok(&*self.is_proper_length_and_alignment(offset, 1)?) }
+ }
+
+ fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Result<&[T]> {
+ unsafe { Ok(std::slice::from_raw_parts(self.is_proper_length_and_alignment(offset, len)?, len)) }
+ }
+
+ fn copy_as<T>(&self, offset: usize) -> Result<T> {
+ self.is_proper_length::<T>(offset)?;
+
+ unsafe {
+ let mut data = std::mem::MaybeUninit::zeroed().assume_init();
+ std::ptr::copy_nonoverlapping(self[offset..].as_ptr(), &mut data as *mut T as *mut u8, std::mem::size_of::<T>());
+ Ok(data)
+ }
+ }
+
+ fn view_as_str(&self, offset: usize) -> Result<&[u8]> {
+ let buffer = &self[offset..];
+ let index = buffer.iter().position(|c| *c == b'\0').ok_or(())?;
+ Ok(&self[offset..offset + index])
+ }
+
+ fn is_proper_length<T>(&self, offset: usize) -> Result<()> {
+ if offset + std::mem::size_of::<T>() <= self.len() {
+ Ok(())
+ } else {
+ Err(())
+ }
+ }
+
+ fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Result<*const T> {
+ self.is_proper_length::<T>(offset * count)?;
+ let ptr = &self[offset] as *const u8 as *const T;
+
+ if ptr.align_offset(std::mem::align_of::<T>()) == 0 {
+ Ok(ptr)
+ } else {
+ Err(())
+ }
+ }
+}
diff --git a/vendor/windows-metadata/src/file/reader.rs b/vendor/windows-metadata/src/file/reader.rs
deleted file mode 100644
index 571a06d5e..000000000
--- a/vendor/windows-metadata/src/file/reader.rs
+++ /dev/null
@@ -1,359 +0,0 @@
-use super::*;
-
-pub trait RowReader<'a> {
- fn row_file<R: AsRow>(&self, row: R) -> &'a File;
-
- fn row_usize<R: AsRow>(&self, row: R, column: usize) -> usize {
- let file = self.row_file(row);
- let row = row.to_row();
- file.usize(row.row, R::TABLE, column)
- }
-
- fn row_str<R: AsRow>(&self, row: R, column: usize) -> &'a str {
- let file = self.row_file(row);
- let offset = file.strings + self.row_usize(row, column);
- let bytes = &file.bytes[offset..];
- let nul_pos = bytes.iter().position(|&c| c == 0).expect("expected null-terminated C-string");
- std::str::from_utf8(&bytes[..nul_pos]).expect("expected valid utf-8 C-string")
- }
-
- fn row_blob<R: AsRow>(&self, row: R, column: usize) -> Blob<'a> {
- let file = self.row_file(row);
- let offset = file.blobs + self.row_usize(row, column);
- let initial_byte = file.bytes[offset];
-
- let (blob_size, blob_size_bytes) = match initial_byte >> 5 {
- 0..=3 => (initial_byte & 0x7f, 1),
- 4..=5 => (initial_byte & 0x3f, 2),
- 6 => (initial_byte & 0x1f, 4),
- rest => unimplemented!("{rest:?}"),
- };
-
- let mut blob_size = blob_size as usize;
-
- for byte in &file.bytes[offset + 1..offset + blob_size_bytes] {
- blob_size = blob_size.checked_shl(8).unwrap_or(0) + (*byte as usize);
- }
-
- let offset = offset + blob_size_bytes;
- Blob::new(row.file(), &file.bytes[offset..offset + blob_size])
- }
-
- fn row_list<R: AsRow, L: AsRow>(&self, row: R, column: usize) -> RowIterator<L> {
- let file = self.row_file(row);
- let first = self.row_usize(row, column) - 1;
- let next = row.next();
- let last = if next.index() < file.tables[R::TABLE].len { self.row_usize(next, column) - 1 } else { file.tables[L::TABLE].len };
- RowIterator::new(row.file(), first..last)
- }
-
- fn row_equal_range<R: AsRow, L: AsRow>(&self, row: R, column: usize, value: usize) -> RowIterator<L> {
- let file = self.row_file(row);
- let mut first = 0;
- let mut last = file.tables[L::TABLE].len;
- let mut count = last;
-
- loop {
- if count == 0 {
- last = first;
- break;
- }
-
- let count2 = count / 2;
- let middle = first + count2;
- let middle_value = file.usize(middle, L::TABLE, column);
-
- match middle_value.cmp(&value) {
- Ordering::Less => {
- first = middle + 1;
- count -= count2 + 1;
- }
- Ordering::Greater => count = count2,
- Ordering::Equal => {
- let first2 = file.lower_bound_of(L::TABLE, first, middle, column, value);
- first += count;
- last = file.upper_bound_of(L::TABLE, middle + 1, first, column, value);
- first = first2;
- break;
- }
- }
- }
-
- RowIterator::new(row.file(), first..last)
- }
-
- fn row_decode<R: AsRow, T: Decode>(&self, row: R, column: usize) -> T {
- T::decode(row.file(), self.row_usize(row, column))
- }
-
- //
- // Attribute
- //
-
- fn attribute_name(&self, row: Attribute) -> &'a str {
- let AttributeType::MemberRef(row) = self.row_decode(row, 1);
- let MemberRefParent::TypeRef(row) = self.row_decode(row, 0);
- self.type_ref_name(row)
- }
-
- fn attributes<R: AsRow + Into<HasAttribute>>(&self, row: R) -> RowIterator<Attribute> {
- self.row_equal_range(row, 0, row.into().encode())
- }
-
- fn find_attribute<R: AsRow + Into<HasAttribute>>(&self, row: R, name: &str) -> Option<Attribute> {
- self.attributes(row).find(|attribute| self.attribute_name(*attribute) == name)
- }
-
- fn has_attribute<R: AsRow + Into<HasAttribute>>(&self, row: R, name: &str) -> bool {
- self.find_attribute(row, name).is_some()
- }
-
- //
- // Other
- //
-
- fn type_def_or_ref(&self, code: TypeDefOrRef) -> TypeName<'a> {
- match code {
- TypeDefOrRef::TypeDef(row) => TypeName::new(self.type_def_namespace(row), self.type_def_name(row)),
- TypeDefOrRef::TypeRef(row) => TypeName::new(self.type_ref_namespace(row), self.type_ref_name(row)),
- rest => unimplemented!("{rest:?}"),
- }
- }
-
- //
- // ClassLayout
- //
-
- fn class_layout_packing_size(&self, row: ClassLayout) -> usize {
- self.row_usize(row, 0)
- }
-
- //
- // Constant
- //
-
- fn constant_type(&self, row: Constant) -> Type {
- let code = self.row_usize(row, 0);
- Type::from_code(code).expect("Constant type not found")
- }
-
- fn constant_value(&self, row: Constant) -> Value {
- let mut blob = self.row_blob(row, 2);
- match self.constant_type(row) {
- Type::I8 => Value::I8(blob.read_i8()),
- Type::U8 => Value::U8(blob.read_u8()),
- Type::I16 => Value::I16(blob.read_i16()),
- Type::U16 => Value::U16(blob.read_u16()),
- Type::I32 => Value::I32(blob.read_i32()),
- Type::U32 => Value::U32(blob.read_u32()),
- Type::I64 => Value::I64(blob.read_i64()),
- Type::U64 => Value::U64(blob.read_u64()),
- Type::F32 => Value::F32(blob.read_f32()),
- Type::F64 => Value::F64(blob.read_f64()),
- Type::String => Value::String(blob.read_string()),
- rest => unimplemented!("{rest:?}"),
- }
- }
-
- //
- // Field
- //
-
- fn field_flags(&self, row: Field) -> FieldAttributes {
- FieldAttributes(self.row_usize(row, 0) as u16)
- }
-
- fn field_name(&self, row: Field) -> &'a str {
- self.row_str(row, 1)
- }
-
- fn field_constant(&self, row: Field) -> Option<Constant> {
- self.row_equal_range(row, 1, HasConstant::Field(row).encode()).next()
- }
-
- //
- // GenericParam
- //
-
- fn generic_param_number(&self, row: GenericParam) -> u16 {
- self.row_usize(row, 0) as u16
- }
-
- fn generic_param_name(&self, row: GenericParam) -> &'a str {
- self.row_str(row, 3)
- }
-
- //
- // ImplMap
- //
-
- fn impl_map_flags(&self, row: ImplMap) -> PInvokeAttributes {
- PInvokeAttributes(self.row_usize(row, 0))
- }
-
- fn impl_map_scope(&self, row: ImplMap) -> ModuleRef {
- ModuleRef(Row::new(self.row_usize(row, 3) - 1, row.file()))
- }
-
- fn impl_map_import_name(&self, row: ImplMap) -> &'a str {
- self.row_str(row, 2)
- }
-
- //
- // MemberRef
- //
-
- fn member_ref_parent(&self, row: MemberRef) -> MemberRefParent {
- self.row_decode(row, 0)
- }
-
- fn member_ref_signature(&self, row: MemberRef) -> Blob<'a> {
- self.row_blob(row, 2)
- }
-
- //
- // MethodDef
- //
-
- fn method_def_impl_flags(&self, row: MethodDef) -> MethodImplAttributes {
- MethodImplAttributes(self.row_usize(row, 1) as u16)
- }
-
- fn method_def_flags(&self, row: MethodDef) -> MethodAttributes {
- MethodAttributes(self.row_usize(row, 2) as u16)
- }
-
- fn method_def_name(&self, row: MethodDef) -> &'a str {
- self.row_str(row, 3)
- }
-
- fn method_def_params(&self, row: MethodDef) -> RowIterator<Param> {
- self.row_list(row, 5)
- }
-
- fn method_def_impl_map(&self, row: MethodDef) -> Option<ImplMap> {
- self.row_equal_range(row, 1, MemberForwarded::MethodDef(row).encode()).next()
- }
-
- fn method_def_module_name(&self, row: MethodDef) -> String {
- // TODO: riddle should always lower case the module name to avoid allocating here
- let Some(impl_map) = self.method_def_impl_map(row) else {
- return String::new();
- };
-
- self.module_ref_name(self.impl_map_scope(impl_map)).to_lowercase()
- }
-
- //
- // ModuleRef
- //
-
- fn module_ref_name(&self, row: ModuleRef) -> &'a str {
- self.row_str(row, 0)
- }
-
- //
- // NestedClass
- //
-
- fn nested_class_inner(&self, row: NestedClass) -> TypeDef {
- TypeDef(Row::new(self.row_usize(row, 0) - 1, row.file()))
- }
-
- fn nested_class_outer(&self, row: NestedClass) -> TypeDef {
- TypeDef(Row::new(self.row_usize(row, 1) - 1, row.file()))
- }
-
- //
- // Param
- //
-
- fn param_flags(&self, row: Param) -> ParamAttributes {
- ParamAttributes(self.row_usize(row, 0) as u16)
- }
-
- fn param_sequence(&self, row: Param) -> u16 {
- self.row_usize(row, 1) as u16
- }
-
- fn param_name(&self, row: Param) -> &'a str {
- self.row_str(row, 2)
- }
-
- //
- // TypeDef
- //
-
- fn type_def_flags(&self, row: TypeDef) -> TypeAttributes {
- TypeAttributes(self.row_usize(row, 0) as u32)
- }
-
- fn type_def_name(&self, row: TypeDef) -> &'a str {
- self.row_str(row, 1)
- }
-
- fn type_def_namespace(&self, row: TypeDef) -> &'a str {
- self.row_str(row, 2)
- }
-
- fn type_def_extends(&self, row: TypeDef) -> Option<TypeName<'a>> {
- match self.row_usize(row, 3) {
- 0 => None,
- code => Some(self.type_def_or_ref(TypeDefOrRef::decode(row.file(), code))),
- }
- }
-
- fn type_def_methods(&self, row: TypeDef) -> RowIterator<MethodDef> {
- self.row_list(row, 5)
- }
-
- fn type_def_fields(&self, row: TypeDef) -> RowIterator<Field> {
- self.row_list(row, 4)
- }
-
- fn type_def_generics(&self, row: TypeDef) -> RowIterator<GenericParam> {
- self.row_equal_range(row, 2, TypeOrMethodDef::TypeDef(row).encode())
- }
-
- fn type_def_interface_impls(&self, row: TypeDef) -> RowIterator<InterfaceImpl> {
- self.row_equal_range(row, 0, row.0.row + 1)
- }
-
- fn type_def_enclosing_type(&self, row: TypeDef) -> Option<TypeDef> {
- self.row_equal_range::<TypeDef, NestedClass>(row, 0, row.0.row + 1).next().map(|row| TypeDef(Row::new(self.row_usize(row, 1) - 1, row.file())))
- }
-
- fn type_def_class_layout(&self, row: TypeDef) -> Option<ClassLayout> {
- self.row_equal_range(row, 2, row.0.row + 1).next()
- }
-
- //
- // TypeRef
- //
-
- fn type_ref_name(&self, row: TypeRef) -> &'a str {
- self.row_str(row, 1)
- }
-
- fn type_ref_namespace(&self, row: TypeRef) -> &'a str {
- self.row_str(row, 2)
- }
-
- fn type_ref_resolution_scope(&self, row: TypeRef) -> ResolutionScope {
- self.row_decode(row, 0)
- }
-
- //
- // TypeSpec
- //
-
- fn type_spec_signature(&self, row: TypeSpec) -> Blob<'a> {
- self.row_blob(row, 0)
- }
-}
-
-impl<'a> RowReader<'a> for &'a [File] {
- fn row_file<R: AsRow>(&self, row: R) -> &'a File {
- &self[row.to_row().file]
- }
-}
diff --git a/vendor/windows-metadata/src/file/view.rs b/vendor/windows-metadata/src/file/view.rs
deleted file mode 100644
index 31eb1541b..000000000
--- a/vendor/windows-metadata/src/file/view.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-type Result<T> = std::result::Result<T, ()>;
-
-pub trait View {
- fn view_as<T>(&self, offset: usize) -> Result<&T>;
- fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Result<&[T]>;
- fn copy_as<T: Copy>(&self, offset: usize) -> Result<T>;
- fn view_as_str(&self, offset: usize) -> Result<&[u8]>;
- fn is_proper_length<T>(&self, offset: usize) -> Result<()>;
- fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Result<*const T>;
-}
-
-impl View for [u8] {
- fn view_as<T>(&self, offset: usize) -> Result<&T> {
- unsafe { Ok(&*self.is_proper_length_and_alignment(offset, 1)?) }
- }
-
- fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Result<&[T]> {
- unsafe { Ok(std::slice::from_raw_parts(self.is_proper_length_and_alignment(offset, len)?, len)) }
- }
-
- fn copy_as<T>(&self, offset: usize) -> Result<T> {
- self.is_proper_length::<T>(offset)?;
-
- unsafe {
- let mut data = std::mem::MaybeUninit::zeroed().assume_init();
- std::ptr::copy_nonoverlapping(self[offset..].as_ptr(), &mut data as *mut T as *mut u8, std::mem::size_of::<T>());
- Ok(data)
- }
- }
-
- fn view_as_str(&self, offset: usize) -> Result<&[u8]> {
- let buffer = &self[offset..];
- let index = buffer.iter().position(|c| *c == b'\0').ok_or(())?;
- Ok(&self[offset..offset + index])
- }
-
- fn is_proper_length<T>(&self, offset: usize) -> Result<()> {
- if offset + std::mem::size_of::<T>() <= self.len() {
- Ok(())
- } else {
- Err(())
- }
- }
-
- fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Result<*const T> {
- self.is_proper_length::<T>(offset * count)?;
- let ptr = &self[offset] as *const u8 as *const T;
-
- if ptr.align_offset(std::mem::align_of::<T>()) == 0 {
- Ok(ptr)
- } else {
- Err(())
- }
- }
-}
diff --git a/vendor/windows-metadata/src/filter.rs b/vendor/windows-metadata/src/filter.rs
index c13afda44..f9efcfe7e 100644
--- a/vendor/windows-metadata/src/filter.rs
+++ b/vendor/windows-metadata/src/filter.rs
@@ -1,18 +1,16 @@
-use super::*;
-
#[derive(Default)]
-pub struct Filter<'a>(Vec<(&'a str, bool)>);
+pub struct Filter(pub Vec<(String, bool)>);
-impl<'a> Filter<'a> {
- pub fn new(include: &[&'a str], exclude: &[&'a str]) -> Self {
+impl Filter {
+ pub fn new(include: &[&str], exclude: &[&str]) -> Self {
let mut rules = vec![];
for include in include {
- rules.push((*include, true));
+ rules.push((include.to_string(), true));
}
for exclude in exclude {
- rules.push((*exclude, false));
+ rules.push((exclude.to_string(), false));
}
rules.sort_unstable_by(|left, right| {
@@ -25,7 +23,7 @@ impl<'a> Filter<'a> {
}
pub fn includes_namespace(&self, namespace: &str) -> bool {
- if self.is_empty() {
+ if self.0.is_empty() {
return true;
}
@@ -35,12 +33,12 @@ impl<'a> Filter<'a> {
if rule.0.starts_with(namespace) {
return true;
}
- if namespace.starts_with(rule.0) {
+ if namespace.starts_with(&rule.0) {
return true;
}
} else {
// exclude
- if namespace.starts_with(rule.0) {
+ if namespace.starts_with(&rule.0) {
return false;
}
}
@@ -49,27 +47,19 @@ impl<'a> Filter<'a> {
false
}
- pub fn includes_type_name(&self, type_name: TypeName) -> bool {
- if self.is_empty() {
+ pub fn includes_type_name(&self, namespace: &str, name: &str) -> bool {
+ if self.0.is_empty() {
return true;
}
for rule in &self.0 {
- if match_type_name(rule.0, type_name.namespace, type_name.name) {
+ if match_type_name(&rule.0, namespace, name) {
return rule.1;
}
}
false
}
-
- pub fn includes(&self) -> impl Iterator<Item = &str> + '_ {
- self.0.iter().filter_map(|(name, include)| if *include { Some(*name) } else { None })
- }
-
- fn is_empty(&self) -> bool {
- self.0.is_empty()
- }
}
fn match_type_name(rule: &str, namespace: &str, name: &str) -> bool {
@@ -92,8 +82,9 @@ fn match_type_name(rule: &str, namespace: &str, name: &str) -> bool {
mod tests {
use super::*;
- fn includes_type_name(filter: &Filter, full_name: &str) -> bool {
- filter.includes_type_name(TypeName::parse(full_name))
+ fn includes_type_name(filter: &Filter, full_name: &'static str) -> bool {
+ let type_name = crate::TypeName::parse(full_name);
+ filter.includes_type_name(type_name.namespace, type_name.name)
}
#[test]
@@ -116,8 +107,6 @@ mod tests {
let exclude = ["N2", "N3.N4"];
let f = Filter::new(&include, &exclude);
- assert!(!f.is_empty());
-
assert!(!includes_type_name(&f, "NN.T"));
assert!(includes_type_name(&f, "N1.T"));
@@ -135,8 +124,6 @@ mod tests {
let exclude = ["N.N3", "N.N4"];
let f = Filter::new(&include, &exclude);
- assert!(!f.is_empty());
-
assert!(includes_type_name(&f, "N.N1.T"));
assert!(includes_type_name(&f, "N.N2.T"));
@@ -150,8 +137,6 @@ mod tests {
let exclude = ["N.T"];
let f = Filter::new(&include, &exclude);
- assert!(!f.is_empty());
-
assert!(!includes_type_name(&f, "N.T"));
}
}
diff --git a/vendor/windows-metadata/src/guid.rs b/vendor/windows-metadata/src/guid.rs
deleted file mode 100644
index a253530ba..000000000
--- a/vendor/windows-metadata/src/guid.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#![allow(clippy::many_single_char_names)]
-
-use super::*;
-
-#[derive(Clone, PartialEq, Eq, Default)]
-pub struct GUID(pub u32, pub u16, pub u16, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8);
-
-impl GUID {
- pub fn from_args(args: &[(String, Value)]) -> Self {
- fn unwrap_u32(value: &Value) -> u32 {
- match value {
- Value::U32(value) => *value,
- rest => unimplemented!("{rest:?}"),
- }
- }
- fn unwrap_u16(value: &Value) -> u16 {
- match value {
- Value::U16(value) => *value,
- rest => unimplemented!("{rest:?}"),
- }
- }
- fn unwrap_u8(value: &Value) -> u8 {
- match value {
- Value::U8(value) => *value,
- rest => unimplemented!("{rest:?}"),
- }
- }
- Self(unwrap_u32(&args[0].1), unwrap_u16(&args[1].1), unwrap_u16(&args[2].1), unwrap_u8(&args[3].1), unwrap_u8(&args[4].1), unwrap_u8(&args[5].1), unwrap_u8(&args[6].1), unwrap_u8(&args[7].1), unwrap_u8(&args[8].1), unwrap_u8(&args[9].1), unwrap_u8(&args[10].1))
- }
-
- pub fn from_string_args(args: &[&str]) -> Self {
- Self(args[0].parse().unwrap(), args[1].parse().unwrap(), args[2].parse().unwrap(), args[3].parse().unwrap(), args[4].parse().unwrap(), args[5].parse().unwrap(), args[6].parse().unwrap(), args[7].parse().unwrap(), args[8].parse().unwrap(), args[9].parse().unwrap(), args[10].parse().unwrap())
- }
-}
-
-impl std::fmt::Debug for GUID {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{:08x?}-{:04x?}-{:04x?}-{:02x?}{:02x?}-{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}", self.0, self.1, self.2, self.3, self.4, self.5, self.6, self.7, self.8, self.9, self.10)
- }
-}
diff --git a/vendor/windows-metadata/src/imp/mod.rs b/vendor/windows-metadata/src/imp/mod.rs
deleted file mode 100644
index 571d0f063..000000000
--- a/vendor/windows-metadata/src/imp/mod.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-mod bindings;
-pub use bindings::*;
-
-#[repr(C)]
-#[derive(Default)]
-pub struct METADATA_HEADER {
- pub signature: u32,
- pub major_version: u16,
- pub minor_version: u16,
- pub reserved: u32,
- pub length: u32,
- pub version: [u8; 20],
- pub flags: u16,
- pub streams: u16,
-}
-
-pub const METADATA_SIGNATURE: u32 = 0x424A_5342;
-
-/// A coded index (see codes.rs) is a table index that may refer to different tables. The size of the column in memory
-/// must therefore be large enough to hold an index for a row in the largest possible table. This function determines
-/// this size for the given winmd file.
-pub fn coded_index_size(tables: &[usize]) -> usize {
- fn small(row_count: usize, bits: u8) -> bool {
- (row_count as u64) < (1u64 << (16 - bits))
- }
-
- fn bits_needed(value: usize) -> u8 {
- let mut value = value - 1;
- let mut bits: u8 = 1;
- while {
- value >>= 1;
- value != 0
- } {
- bits += 1;
- }
- bits
- }
-
- let bits_needed = bits_needed(tables.len());
-
- if tables.iter().all(|table| small(*table, bits_needed)) {
- 2
- } else {
- 4
- }
-}
diff --git a/vendor/windows-metadata/src/lib.rs b/vendor/windows-metadata/src/lib.rs
index 70a85c5b1..15220b178 100644
--- a/vendor/windows-metadata/src/lib.rs
+++ b/vendor/windows-metadata/src/lib.rs
@@ -1,36 +1,76 @@
-#[doc(hidden)]
-pub mod imp;
+use std::cmp::Ordering;
+use std::collections::*;
mod attributes;
+mod bindings;
mod blob;
mod codes;
+mod column;
mod file;
mod filter;
-mod guid;
+mod reader;
mod row;
+mod table;
+mod tables;
mod r#type;
mod type_name;
pub use attributes::*;
-pub use blob::Blob;
+pub use bindings::*;
+pub use blob::*;
pub use codes::*;
+use column::*;
pub use file::*;
-pub use filter::Filter;
-pub use guid::GUID;
-use imp::*;
-pub use r#type::Type;
+use filter::*;
+pub use r#type::*;
+pub use reader::*;
pub use row::*;
-use std::collections::*;
-pub use type_name::TypeName;
+use table::*;
+pub use tables::*;
+pub use type_name::*;
+
+#[repr(C)]
+#[derive(Default)]
+pub struct METADATA_HEADER {
+ pub signature: u32,
+ pub major_version: u16,
+ pub minor_version: u16,
+ pub reserved: u32,
+ pub length: u32,
+ pub version: [u8; 20],
+ pub flags: u16,
+ pub streams: u16,
+}
-// TODO: move to riddle
-#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
-pub enum TypeKind {
- Interface,
- Class,
- Enum,
- Struct,
- Delegate,
+pub const METADATA_SIGNATURE: u32 = 0x424A_5342;
+
+/// A coded index (see codes.rs) is a table index that may refer to different tables. The size of the column in memory
+/// must therefore be large enough to hold an index for a row in the largest possible table. This function determines
+/// this size for the given winmd file.
+pub fn coded_index_size(tables: &[usize]) -> usize {
+ fn small(row_count: usize, bits: u8) -> bool {
+ (row_count as u64) < (1u64 << (16 - bits))
+ }
+
+ fn bits_needed(value: usize) -> u8 {
+ let mut value = value - 1;
+ let mut bits: u8 = 1;
+ while {
+ value >>= 1;
+ value != 0
+ } {
+ bits += 1;
+ }
+ bits
+ }
+
+ let bits_needed = bits_needed(tables.len());
+
+ if tables.iter().all(|table| small(*table, bits_needed)) {
+ 2
+ } else {
+ 4
+ }
}
#[derive(Debug)]
@@ -47,8 +87,7 @@ pub enum Value {
F32(f32),
F64(f64),
String(String),
- TypeName(String),
- TypeRef(TypeDefOrRef),
+ TypeName(TypeName),
EnumDef(TypeDef, Box<Self>),
}
@@ -58,406 +97,17 @@ pub struct MethodDefSig {
pub params: Vec<Type>,
}
-#[derive(Clone, Debug)]
-pub enum Item {
- Type(TypeDef),
- Const(Field),
- // TODO: get rid of the trailing String - that's just a hack to get around a silly Win32 metadata deficiency where parsing method signatures
- // requires knowing which namespace the method's surrounding interface was defined in.
- Fn(MethodDef, String),
-}
-
-pub struct Reader<'a> {
- files: &'a [File],
- items: BTreeMap<&'a str, BTreeMap<&'a str, Vec<Item>>>,
-
- // TODO: riddle should just avoid nested structs
- nested: HashMap<TypeDef, BTreeMap<&'a str, TypeDef>>,
-}
-
-impl<'a> Reader<'a> {
- pub fn new(files: &'a [File]) -> Self {
- let mut items = BTreeMap::<&'a str, BTreeMap<&'a str, Vec<Item>>>::new();
- let mut nested = HashMap::<TypeDef, BTreeMap<&'a str, TypeDef>>::new();
- for (file_index, file) in files.iter().enumerate() {
- for def in file.table::<TypeDef>(file_index) {
- let namespace = files.type_def_namespace(def);
- if namespace.is_empty() {
- continue;
- }
- let namespace_items = items.entry(namespace).or_default();
- let name = files.type_def_name(def);
- if name == "Apis" {
- for method in files.type_def_methods(def) {
- let name = files.method_def_name(method);
- namespace_items.entry(name).or_default().push(Item::Fn(method, namespace.to_string()));
- }
- for field in files.type_def_fields(def) {
- let name = files.field_name(field);
- namespace_items.entry(name).or_default().push(Item::Const(field));
- }
- } else {
- namespace_items.entry(trim_tick(name)).or_default().push(Item::Type(def));
-
- // TODO: these should all be fields on the Apis class so we don't have to go looking for all of these as well.
- if files.type_def_extends(def) == Some(TypeName::Enum) && !files.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) && !files.has_attribute(def, "ScopedEnumAttribute") {
- for field in files.type_def_fields(def).filter(|field| files.field_flags(*field).contains(FieldAttributes::Literal)) {
- let name = files.field_name(field);
- namespace_items.entry(name).or_default().push(Item::Const(field));
- }
- }
- }
- }
- for key in file.table::<NestedClass>(file_index) {
- let inner = files.nested_class_inner(key);
- let outer = files.nested_class_outer(key);
- let name = files.type_def_name(inner);
- nested.entry(outer).or_default().insert(name, inner);
- }
- }
- Self { files, items, nested }
- }
-
- pub fn namespaces(&self) -> impl Iterator<Item = &str> + '_ {
- self.items.keys().copied()
- }
-
- pub fn items(&'a self, filter: &'a Filter) -> impl Iterator<Item = Item> + '_ {
- self.items.iter().filter(move |(namespace, _)| filter.includes_namespace(namespace)).flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| filter.includes_type_name(TypeName::new(namespace, name)))).flat_map(move |(_, items)| items).cloned()
- }
-
- pub fn namespace_items(&'a self, namespace: &str, filter: &'a Filter) -> impl Iterator<Item = Item> + '_ {
- self.items.get_key_value(namespace).into_iter().flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| filter.includes_type_name(TypeName::new(namespace, name)))).flat_map(move |(_, items)| items).cloned()
- }
-
- fn get_item(&self, type_name: TypeName) -> impl Iterator<Item = Item> + '_ {
- if let Some(items) = self.items.get(type_name.namespace) {
- if let Some(items) = items.get(type_name.name) {
- return Some(items.iter().cloned()).into_iter().flatten();
- }
- }
- None.into_iter().flatten()
- }
-
- pub fn get_type_def(&self, type_name: TypeName) -> impl Iterator<Item = TypeDef> + '_ {
- self.get_item(type_name).filter_map(|item| if let Item::Type(def) = item { Some(def) } else { None })
- }
-
- pub fn get_method_def(&self, type_name: TypeName) -> impl Iterator<Item = (MethodDef, String)> + '_ {
- self.get_item(type_name).filter_map(|item| if let Item::Fn(def, namespace) = item { Some((def, namespace)) } else { None })
- }
-
- pub fn nested_types(&self, type_def: TypeDef) -> impl Iterator<Item = TypeDef> + '_ {
- self.nested.get(&type_def).map(|map| map.values().copied()).into_iter().flatten()
- }
-
- pub fn attribute_args(&self, row: Attribute) -> Vec<(String, Value)> {
- let AttributeType::MemberRef(member) = self.row_decode(row, 1);
- let mut sig = self.member_ref_signature(member);
- let mut values = self.row_blob(row, 2);
- let _prolog = values.read_u16();
- let _this_and_gen_param_count = sig.read_usize();
- let fixed_arg_count = sig.read_usize();
- let _ret_type = sig.read_usize();
- let mut args: Vec<(String, Value)> = Vec::with_capacity(fixed_arg_count);
-
- for _ in 0..fixed_arg_count {
- let arg = match self.type_from_blob(&mut sig, None, &[]) {
- Type::Bool => Value::Bool(values.read_bool()),
- Type::I8 => Value::I8(values.read_i8()),
- Type::U8 => Value::U8(values.read_u8()),
- Type::I16 => Value::I16(values.read_i16()),
- Type::U16 => Value::U16(values.read_u16()),
- Type::I32 => Value::I32(values.read_i32()),
- Type::U32 => Value::U32(values.read_u32()),
- Type::I64 => Value::I64(values.read_i64()),
- Type::U64 => Value::U64(values.read_u64()),
- Type::String => Value::String(values.read_str().to_string()),
- Type::TypeName => Value::TypeName(values.read_str().to_string()),
- Type::TypeDef(def, _) => Value::EnumDef(def, Box::new(values.read_integer(self.type_def_underlying_type(def)))),
- rest => unimplemented!("{rest:?}"),
- };
-
- args.push((String::new(), arg));
- }
-
- let named_arg_count = values.read_u16();
- args.reserve(named_arg_count as usize);
-
- for _ in 0..named_arg_count {
- let _id = values.read_u8();
- let arg_type = values.read_u8();
- let mut name = values.read_str().to_string();
- let arg = match arg_type {
- ELEMENT_TYPE_BOOLEAN => Value::Bool(values.read_bool()),
- ELEMENT_TYPE_I2 => Value::I16(values.read_i16()),
- ELEMENT_TYPE_I4 => Value::I32(values.read_i32()),
- ELEMENT_TYPE_U4 => Value::U32(values.read_u32()),
- ELEMENT_TYPE_STRING => Value::String(values.read_str().to_string()),
- 0x50 => Value::TypeName(values.read_str().to_string()),
- 0x55 => {
- let def = self.get_type_def(TypeName::parse(&name)).next().expect("Type not found");
- name = values.read_str().into();
- Value::EnumDef(def, Box::new(values.read_integer(self.type_def_underlying_type(def))))
- }
- rest => unimplemented!("{rest:?}"),
- };
- args.push((name, arg));
- }
-
- assert_eq!(sig.slice.len(), 0);
- assert_eq!(values.slice.len(), 0);
-
- args
- }
-
- // TODO: enclosing craziness is only needed for nested structs - get rid of those in riddle and this goes away.
- pub fn field_type(&self, row: Field, enclosing: Option<TypeDef>) -> Type {
- let mut blob = self.row_blob(row, 2);
- blob.read_usize();
- blob.read_modifiers();
- let def = self.type_from_blob(&mut blob, enclosing, &[]);
-
- if self.has_attribute(row, "ConstAttribute") {
- def.to_const_type().to_const_ptr()
- } else {
- def
- }
- }
-
- pub fn interface_impl_type(&self, row: InterfaceImpl, generics: &[Type]) -> Type {
- self.type_from_ref(self.row_decode(row, 1), None, generics)
- }
-
- pub fn method_def_signature(&self, method: MethodDef, generics: &[Type]) -> MethodDefSig {
- let mut blob = self.row_blob(method, 4);
- let call_flags = MethodCallAttributes(blob.read_usize() as u8);
- let params = blob.read_usize();
- let return_type = self.type_from_blob(&mut blob, None, generics);
-
- MethodDefSig { call_flags, return_type, params: (0..params).map(|_| self.type_from_blob(&mut blob, None, generics)).collect() }
- }
-
- pub fn method_def_size(&self, method: MethodDef) -> usize {
- let sig = self.method_def_signature(method, &[]);
- sig.params.iter().fold(0, |sum, param| sum + std::cmp::max(4, self.type_size(param)))
- }
-
- pub fn type_def_type_name(&self, row: TypeDef) -> TypeName {
- TypeName::new(self.type_def_namespace(row), self.type_def_name(row))
- }
-
- pub fn type_def_underlying_type(&self, row: TypeDef) -> Type {
- let field = self.type_def_fields(row).next().expect("Field not found");
- if let Some(constant) = self.field_constant(field) {
- self.constant_type(constant)
- } else {
- self.field_type(field, Some(row))
- }
- }
-
- pub fn type_def_kind(&self, row: TypeDef) -> TypeKind {
- match self.type_def_extends(row) {
- None => TypeKind::Interface,
- Some(TypeName::Enum) => TypeKind::Enum,
- Some(TypeName::Delegate) => TypeKind::Delegate,
- Some(TypeName::Struct) => TypeKind::Struct,
- Some(_) => TypeKind::Class,
- }
- }
-
- pub fn type_def_size(&self, def: TypeDef) -> usize {
- match self.type_def_kind(def) {
- TypeKind::Struct => {
- if self.type_def_flags(def).contains(TypeAttributes::ExplicitLayout) {
- self.type_def_fields(def).map(|field| self.type_size(&self.field_type(field, Some(def)))).max().unwrap_or(1)
- } else {
- let mut sum = 0;
- for field in self.type_def_fields(def) {
- let size = self.type_size(&self.field_type(field, Some(def)));
- let align = self.type_align(&self.field_type(field, Some(def)));
- sum = (sum + (align - 1)) & !(align - 1);
- sum += size;
- }
- sum
- }
- }
- TypeKind::Enum => self.type_size(&self.type_def_underlying_type(def)),
- _ => 4,
- }
- }
-
- fn type_def_align(&self, def: TypeDef) -> usize {
- match self.type_def_kind(def) {
- TypeKind::Struct => self.type_def_fields(def).map(|field| self.type_align(&self.field_type(field, Some(def)))).max().unwrap_or(1),
- TypeKind::Enum => self.type_align(&self.type_def_underlying_type(def)),
- _ => 4,
- }
- }
-
- fn type_align(&self, ty: &Type) -> usize {
- match ty {
- Type::I8 | Type::U8 => 1,
- Type::I16 | Type::U16 => 2,
- Type::I64 | Type::U64 | Type::F64 => 8,
- Type::GUID => 4,
- Type::TypeDef(def, _) => self.type_def_align(*def),
- Type::Win32Array(ty, len) => self.type_align(ty) * len,
- _ => 4,
- }
- }
-
- // TODO: this shouldn't be public - needed to work around Win32 metadata hackery.
- pub fn type_size(&self, ty: &Type) -> usize {
- match ty {
- Type::I8 | Type::U8 => 1,
- Type::I16 | Type::U16 => 2,
- Type::I64 | Type::U64 | Type::F64 => 8,
- Type::GUID => 16,
- Type::TypeDef(def, _) => self.type_def_size(*def),
- Type::Win32Array(ty, len) => self.type_size(ty) * len,
- Type::PrimitiveOrEnum(ty, _) => self.type_size(ty),
- _ => 4,
- }
- }
-
- pub fn type_def_or_ref(&self, code: TypeDefOrRef) -> TypeName {
- match code {
- TypeDefOrRef::TypeDef(row) => TypeName::new(self.type_def_namespace(row), self.type_def_name(row)),
- TypeDefOrRef::TypeRef(row) => TypeName::new(self.type_ref_namespace(row), self.type_ref_name(row)),
- rest => unimplemented!("{rest:?}"),
- }
- }
-
- fn type_from_ref(&self, code: TypeDefOrRef, enclosing: Option<TypeDef>, generics: &[Type]) -> Type {
- if let TypeDefOrRef::TypeSpec(def) = code {
- let mut blob = self.type_spec_signature(def);
- return self.type_from_blob_impl(&mut blob, None, generics);
- }
-
- let mut full_name = self.type_def_or_ref(code);
-
- // TODO: remove this
- for (known_name, kind) in CORE_TYPES {
- if full_name == known_name {
- return kind;
- }
- }
-
- // TODO: remove this
- for (from, to) in REMAP_TYPES {
- if full_name == from {
- full_name = to;
- break;
- }
- }
-
- if let Some(outer) = enclosing {
- if full_name.namespace.is_empty() {
- let nested = &self.nested[&outer];
- let Some(inner) = nested.get(full_name.name) else {
- panic!("Nested type not found: {}.{}", self.type_def_type_name(outer), full_name.name);
- };
- return Type::TypeDef(*inner, Vec::new());
- }
- }
-
- if let Some(def) = self.get_type_def(full_name).next() {
- Type::TypeDef(def, Vec::new())
- } else {
- Type::TypeRef(code)
- }
- }
-
- // TODO: this shouldn't be public
- pub fn type_from_blob(&self, blob: &mut Blob, enclosing: Option<TypeDef>, generics: &[Type]) -> Type {
- // Used by WinRT to indicate that a struct input parameter is passed by reference rather than by value on the ABI.
- let is_const = blob.read_modifiers().iter().any(|def| self.type_def_or_ref(*def) == TypeName::IsConst);
-
- // Used by WinRT to indicate an output parameter, but there are other ways to determine this direction so here
- // it is only used to distinguish between slices and heap-allocated arrays.
- let is_ref = blob.read_expected(ELEMENT_TYPE_BYREF as usize);
-
- if blob.read_expected(ELEMENT_TYPE_VOID as usize) {
- return Type::Void;
- }
-
- let is_array = blob.read_expected(ELEMENT_TYPE_SZARRAY as usize); // Used by WinRT to indicate an array
-
- let mut pointers = 0;
-
- while blob.read_expected(ELEMENT_TYPE_PTR as usize) {
- pointers += 1;
- }
-
- let kind = self.type_from_blob_impl(blob, enclosing, generics);
-
- if pointers > 0 {
- Type::MutPtr(Box::new(kind), pointers)
- } else if is_const {
- Type::ConstRef(Box::new(kind))
- } else if is_array {
- if is_ref {
- Type::WinrtArrayRef(Box::new(kind))
- } else {
- Type::WinrtArray(Box::new(kind))
- }
- } else {
- kind
- }
- }
-
- fn type_from_blob_impl(&self, blob: &mut Blob, enclosing: Option<TypeDef>, generics: &[Type]) -> Type {
- let code = blob.read_usize();
-
- if let Some(code) = Type::from_code(code) {
- return code;
- }
-
- match code as u8 {
- ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS => self.type_from_ref(TypeDefOrRef::decode(blob.file, blob.read_usize()), enclosing, generics),
- ELEMENT_TYPE_VAR => generics.get(blob.read_usize()).unwrap_or(&Type::Void).clone(),
- ELEMENT_TYPE_ARRAY => {
- let kind = self.type_from_blob(blob, enclosing, generics);
- let _rank = blob.read_usize();
- let _count = blob.read_usize();
- let bounds = blob.read_usize();
- Type::Win32Array(Box::new(kind), bounds)
- }
- ELEMENT_TYPE_GENERICINST => {
- blob.read_usize(); // ELEMENT_TYPE_VALUETYPE or ELEMENT_TYPE_CLASS
-
- let type_name = self.type_def_or_ref(TypeDefOrRef::decode(blob.file, blob.read_usize()));
- let def = self.get_type_def(type_name).next().unwrap_or_else(|| panic!("Type not found: {}", type_name));
- let mut args = Vec::with_capacity(blob.read_usize());
-
- for _ in 0..args.capacity() {
- args.push(self.type_from_blob_impl(blob, enclosing, generics));
- }
-
- Type::TypeDef(def, args)
- }
- rest => unimplemented!("{rest:?}"),
- }
- }
-}
-
-impl<'a> RowReader<'a> for Reader<'a> {
- fn row_file<R: AsRow>(&self, row: R) -> &'a File {
- &self.files[row.to_row().file]
+impl MethodDefSig {
+ pub fn size(&self) -> usize {
+ self.params.iter().fold(0, |sum, param| sum + std::cmp::max(4, param.size()))
}
}
-fn trim_tick(name: &str) -> &str {
- if name.as_bytes().iter().rev().nth(1) == Some(&b'`') {
- &name[..name.len() - 2]
- } else {
- name
- }
+#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
+pub enum TypeKind {
+ Interface,
+ Class,
+ Enum,
+ Struct,
+ Delegate,
}
-
-// TODO: this should be in riddle's Rust generator if at all - perhaps as convertible types rather than remapped types since there's already some precedent for that.
-pub const REMAP_TYPES: [(TypeName, TypeName); 2] = [(TypeName::D2D_MATRIX_3X2_F, TypeName::Matrix3x2), (TypeName::D3DMATRIX, TypeName::Matrix4x4)];
-
-// TODO: get rid of at least the second tuple if not the whole thing.
-pub const CORE_TYPES: [(TypeName, Type); 11] = [(TypeName::GUID, Type::GUID), (TypeName::IUnknown, Type::IUnknown), (TypeName::HResult, Type::HRESULT), (TypeName::HRESULT, Type::HRESULT), (TypeName::HSTRING, Type::String), (TypeName::BSTR, Type::BSTR), (TypeName::IInspectable, Type::IInspectable), (TypeName::PSTR, Type::PSTR), (TypeName::PWSTR, Type::PWSTR), (TypeName::Type, Type::TypeName), (TypeName::CHAR, Type::U8)];
diff --git a/vendor/windows-metadata/src/reader.rs b/vendor/windows-metadata/src/reader.rs
new file mode 100644
index 000000000..3445a7ad2
--- /dev/null
+++ b/vendor/windows-metadata/src/reader.rs
@@ -0,0 +1,255 @@
+use super::*;
+
+#[derive(Clone)]
+pub enum Item {
+ Type(TypeDef),
+ Const(Field),
+ // TODO: get rid of the trailing String - that's just a hack to get around a silly Win32 metadata deficiency where parsing method signatures
+ // requires knowing which namespace the method's surrounding interface was defined in.
+ Fn(MethodDef, &'static str),
+}
+
+pub struct Reader {
+ // TODO: get rid of inner Vec - that's just a hack to support multi-arch structs in Win32 metadata.
+ items: BTreeMap<&'static str, BTreeMap<&'static str, Vec<Item>>>,
+
+ // TODO: riddle should just avoid nested structs
+ nested: HashMap<TypeDef, BTreeMap<&'static str, TypeDef>>,
+
+ // The reader needs to store the filter since standalone code generation needs more than just the filtered items
+ // in order to chase dependencies automatically. This is why `Reader::filter` can't just filter everything up front.
+ filter: Filter,
+}
+
+impl Reader {
+ pub fn new(files: Vec<File>) -> &'static Self {
+ Self::filter(files, &[], &[])
+ }
+
+ pub fn filter(files: Vec<File>, include: &[&str], exclude: &[&str]) -> &'static Self {
+ let reader: &'static mut Reader = Box::leak(Box::new(Self { items: Default::default(), nested: Default::default(), filter: Filter::new(include, exclude) }));
+
+ for mut file in files {
+ file.reader = reader as *mut Reader;
+ let file = Box::leak(Box::new(file));
+
+ for def in file.table::<TypeDef>() {
+ let namespace = def.namespace();
+
+ if namespace.is_empty() {
+ continue;
+ }
+
+ let namespace_items = reader.items.entry(namespace).or_default();
+ let name = def.name();
+
+ if name == "Apis" {
+ for method in def.methods() {
+ namespace_items.entry(method.name()).or_default().push(Item::Fn(method, namespace));
+ }
+
+ for field in def.fields() {
+ namespace_items.entry(field.name()).or_default().push(Item::Const(field));
+ }
+ } else {
+ namespace_items.entry(name).or_default().push(Item::Type(def));
+
+ // TODO: these should all be fields on the Apis class so we don't have to go looking for all of these as well.
+ if def.extends() == Some(TypeName::Enum) && !def.flags().contains(TypeAttributes::WindowsRuntime) && !def.has_attribute("ScopedEnumAttribute") {
+ for field in def.fields().filter(|field| field.flags().contains(FieldAttributes::Literal)) {
+ namespace_items.entry(field.name()).or_default().push(Item::Const(field));
+ }
+ }
+ }
+ }
+
+ for key in file.table::<NestedClass>() {
+ let inner = key.inner();
+ reader.nested.entry(key.outer()).or_default().insert(inner.name(), inner);
+ }
+ }
+
+ reader
+ }
+
+ pub fn includes_namespace(&self, namespace: &str) -> bool {
+ self.filter.includes_namespace(namespace)
+ }
+
+ pub fn namespaces(&self) -> impl Iterator<Item = &str> + '_ {
+ self.items.keys().copied()
+ }
+
+ pub fn items(&self) -> impl Iterator<Item = Item> + '_ {
+ self.items.iter().filter(move |(namespace, _)| self.filter.includes_namespace(namespace)).flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| self.filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned()
+ }
+
+ pub fn namespace_items(&self, namespace: &str) -> impl Iterator<Item = Item> + '_ {
+ self.items.get_key_value(namespace).into_iter().flat_map(move |(namespace, items)| items.iter().filter(move |(name, _)| self.filter.includes_type_name(namespace, name))).flat_map(move |(_, items)| items).cloned()
+ }
+
+ pub fn unused(&self) -> impl Iterator<Item = &str> + '_ {
+ self.filter.0.iter().filter_map(|(name, _)| if self.is_unused(name) { Some(name.as_str()) } else { None })
+ }
+
+ fn is_unused(&self, filter: &str) -> bool {
+ // Match namespaces
+ if self.items.contains_key(filter) {
+ return false;
+ }
+
+ // Match type names
+ if let Some((namespace, name)) = filter.rsplit_once('.') {
+ if self.items.get(namespace).is_some_and(|items| items.contains_key(name)) {
+ return false;
+ }
+ }
+
+ // Match empty parent namespaces
+ for namespace in self.items.keys() {
+ if namespace.len() > filter.len() && namespace.starts_with(filter) && namespace.as_bytes()[filter.len()] == b'.' {
+ return false;
+ }
+ }
+
+ true
+ }
+
+ fn get_item(&self, namespace: &str, name: &str) -> impl Iterator<Item = Item> + '_ {
+ if let Some(items) = self.items.get(namespace) {
+ if let Some(items) = items.get(name) {
+ return Some(items.iter().cloned()).into_iter().flatten();
+ }
+ }
+ None.into_iter().flatten()
+ }
+
+ pub fn get_type_def(&self, namespace: &str, name: &str) -> impl Iterator<Item = TypeDef> + '_ {
+ self.get_item(namespace, name).filter_map(|item| if let Item::Type(def) = item { Some(def) } else { None })
+ }
+
+ pub fn get_method_def(&self, namespace: &str, name: &str) -> impl Iterator<Item = (MethodDef, &'static str)> + '_ {
+ self.get_item(namespace, name).filter_map(|item| if let Item::Fn(def, namespace) = item { Some((def, namespace)) } else { None })
+ }
+
+ pub fn nested_types(&self, type_def: TypeDef) -> impl Iterator<Item = TypeDef> + '_ {
+ self.nested.get(&type_def).map(|map| map.values().copied()).into_iter().flatten()
+ }
+
+ pub fn type_from_ref(&self, code: TypeDefOrRef, enclosing: Option<TypeDef>, generics: &[Type]) -> Type {
+ if let TypeDefOrRef::TypeSpec(def) = code {
+ let mut blob = def.blob(0);
+ return self.type_from_blob_impl(&mut blob, None, generics);
+ }
+
+ let mut full_name = code.type_name();
+
+ // TODO: remove this
+ for (known_name, kind) in CORE_TYPES {
+ if full_name == known_name {
+ return kind;
+ }
+ }
+
+ // TODO: remove this
+ for (from, to) in REMAP_TYPES {
+ if full_name == from {
+ full_name = to;
+ break;
+ }
+ }
+
+ if let Some(outer) = enclosing {
+ if full_name.namespace.is_empty() {
+ let nested = &self.nested[&outer];
+ let Some(inner) = nested.get(full_name.name) else {
+ panic!("Nested type not found: {}.{}", outer.type_name(), full_name.name);
+ };
+ return Type::TypeDef(*inner, Vec::new());
+ }
+ }
+
+ if let Some(def) = self.get_type_def(full_name.namespace, full_name.name).next() {
+ Type::TypeDef(def, Vec::new())
+ } else {
+ Type::TypeRef(full_name)
+ }
+ }
+
+ pub fn type_from_blob(&self, blob: &mut Blob, enclosing: Option<TypeDef>, generics: &[Type]) -> Type {
+ // Used by WinRT to indicate that a struct input parameter is passed by reference rather than by value on the ABI.
+ let is_const = blob.read_modifiers().iter().any(|def| def.type_name() == TypeName::IsConst);
+
+ // Used by WinRT to indicate an output parameter, but there are other ways to determine this direction so here
+ // it is only used to distinguish between slices and heap-allocated arrays.
+ let is_ref = blob.read_expected(ELEMENT_TYPE_BYREF as usize);
+
+ if blob.read_expected(ELEMENT_TYPE_VOID as usize) {
+ return Type::Void;
+ }
+
+ let is_array = blob.read_expected(ELEMENT_TYPE_SZARRAY as usize); // Used by WinRT to indicate an array
+
+ let mut pointers = 0;
+
+ while blob.read_expected(ELEMENT_TYPE_PTR as usize) {
+ pointers += 1;
+ }
+
+ let kind = self.type_from_blob_impl(blob, enclosing, generics);
+
+ if pointers > 0 {
+ Type::MutPtr(Box::new(kind), pointers)
+ } else if is_const {
+ Type::ConstRef(Box::new(kind))
+ } else if is_array {
+ if is_ref {
+ Type::WinrtArrayRef(Box::new(kind))
+ } else {
+ Type::WinrtArray(Box::new(kind))
+ }
+ } else {
+ kind
+ }
+ }
+
+ fn type_from_blob_impl(&self, blob: &mut Blob, enclosing: Option<TypeDef>, generics: &[Type]) -> Type {
+ let code = blob.read_usize();
+
+ if let Some(code) = Type::from_code(code) {
+ return code;
+ }
+
+ match code as u8 {
+ ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS => self.type_from_ref(TypeDefOrRef::decode(blob.file, blob.read_usize()), enclosing, generics),
+ ELEMENT_TYPE_VAR => generics.get(blob.read_usize()).unwrap_or(&Type::Void).clone(),
+ ELEMENT_TYPE_ARRAY => {
+ let kind = self.type_from_blob(blob, enclosing, generics);
+ let _rank = blob.read_usize();
+ let _count = blob.read_usize();
+ let bounds = blob.read_usize();
+ Type::Win32Array(Box::new(kind), bounds)
+ }
+ ELEMENT_TYPE_GENERICINST => {
+ blob.read_usize(); // ELEMENT_TYPE_VALUETYPE or ELEMENT_TYPE_CLASS
+
+ let type_name = TypeDefOrRef::decode(blob.file, blob.read_usize()).type_name();
+ let def = self.get_type_def(type_name.namespace, type_name.name).next().unwrap_or_else(|| panic!("Type not found: {}", type_name));
+ let mut args = Vec::with_capacity(blob.read_usize());
+
+ for _ in 0..args.capacity() {
+ args.push(self.type_from_blob_impl(blob, enclosing, generics));
+ }
+
+ Type::TypeDef(def, args)
+ }
+ rest => unimplemented!("{rest:?}"),
+ }
+ }
+}
+
+// TODO: this should be in riddle's Rust generator if at all - perhaps as convertible types rather than remapped types since there's already some precedent for that.
+pub const REMAP_TYPES: [(TypeName, TypeName); 2] = [(TypeName::D2D_MATRIX_3X2_F, TypeName::Matrix3x2), (TypeName::D3DMATRIX, TypeName::Matrix4x4)];
+
+// TODO: get rid of at least the second tuple if not the whole thing.
+pub const CORE_TYPES: [(TypeName, Type); 11] = [(TypeName::GUID, Type::GUID), (TypeName::IUnknown, Type::IUnknown), (TypeName::HResult, Type::HRESULT), (TypeName::HRESULT, Type::HRESULT), (TypeName::HSTRING, Type::String), (TypeName::BSTR, Type::BSTR), (TypeName::IInspectable, Type::IInspectable), (TypeName::PSTR, Type::PSTR), (TypeName::PWSTR, Type::PWSTR), (TypeName::Type, Type::Type), (TypeName::CHAR, Type::U8)];
diff --git a/vendor/windows-metadata/src/row.rs b/vendor/windows-metadata/src/row.rs
index 4e0c30593..4b99f5685 100644
--- a/vendor/windows-metadata/src/row.rs
+++ b/vendor/windows-metadata/src/row.rs
@@ -1,16 +1,18 @@
-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
+use super::*;
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub struct Row {
- pub row: usize,
- pub file: usize,
+ pub file: &'static File,
+ pub index: usize,
}
impl Row {
- pub fn new(row: usize, file: usize) -> Self {
- Self { row, file }
+ pub fn new(file: &'static File, index: usize) -> Self {
+ Self { file, index }
}
fn next(&self) -> Self {
- Self { row: self.row + 1, file: self.file }
+ Self { file: self.file, index: self.index + 1 }
}
}
@@ -19,27 +21,117 @@ pub trait AsRow: Copy {
fn to_row(&self) -> Row;
fn from_row(row: Row) -> Self;
- fn file(&self) -> usize {
+ fn file(&self) -> &'static File {
self.to_row().file
}
+ fn reader(&self) -> &'static Reader {
+ // Safety: At this point the File is already pointing to a valid Reader.
+ unsafe { &*self.file().reader }
+ }
+
fn index(&self) -> usize {
- self.to_row().row
+ self.to_row().index
}
fn next(&self) -> Self {
Self::from_row(self.to_row().next())
}
+
+ fn usize(&self, column: usize) -> usize {
+ self.file().usize(self.index(), Self::TABLE, column)
+ }
+
+ fn str(&self, column: usize) -> &'static str {
+ let file = self.file();
+ let offset = file.strings + self.usize(column);
+ let bytes = &file.bytes[offset..];
+ let nul_pos = bytes.iter().position(|&c| c == 0).expect("expected null-terminated C-string");
+ std::str::from_utf8(&bytes[..nul_pos]).expect("expected valid utf-8 C-string")
+ }
+
+ fn row(&self, column: usize) -> Row {
+ Row::new(self.file(), self.usize(column) - 1)
+ }
+
+ fn decode<T: Decode>(&self, column: usize) -> T {
+ T::decode(self.file(), self.usize(column))
+ }
+
+ fn blob(&self, column: usize) -> Blob {
+ let file = self.file();
+ let offset = file.blobs + self.usize(column);
+ let initial_byte = file.bytes[offset];
+
+ let (blob_size, blob_size_bytes) = match initial_byte >> 5 {
+ 0..=3 => (initial_byte & 0x7f, 1),
+ 4..=5 => (initial_byte & 0x3f, 2),
+ 6 => (initial_byte & 0x1f, 4),
+ rest => unimplemented!("{rest:?}"),
+ };
+
+ let mut blob_size = blob_size as usize;
+
+ for byte in &file.bytes[offset + 1..offset + blob_size_bytes] {
+ blob_size = blob_size.checked_shl(8).unwrap_or(0) + (*byte as usize);
+ }
+
+ let offset = offset + blob_size_bytes;
+ Blob::new(file, &file.bytes[offset..offset + blob_size])
+ }
+
+ fn list<R: AsRow>(&self, column: usize) -> RowIterator<R> {
+ let file = self.file();
+ let first = self.usize(column) - 1;
+ let next = self.next();
+ let last = if next.index() < file.tables[Self::TABLE].len { next.usize(column) - 1 } else { file.tables[R::TABLE].len };
+ RowIterator::new(file, first..last)
+ }
+
+ fn equal_range<L: AsRow>(&self, column: usize, value: usize) -> RowIterator<L> {
+ let file = self.file();
+ let mut first = 0;
+ let mut last = file.tables[L::TABLE].len;
+ let mut count = last;
+
+ loop {
+ if count == 0 {
+ last = first;
+ break;
+ }
+
+ let count2 = count / 2;
+ let middle = first + count2;
+ let middle_value = file.usize(middle, L::TABLE, column);
+
+ match middle_value.cmp(&value) {
+ Ordering::Less => {
+ first = middle + 1;
+ count -= count2 + 1;
+ }
+ Ordering::Greater => count = count2,
+ Ordering::Equal => {
+ let first2 = file.lower_bound_of(L::TABLE, first, middle, column, value);
+ first += count;
+ last = file.upper_bound_of(L::TABLE, middle + 1, first, column, value);
+ first = first2;
+ break;
+ }
+ }
+ }
+
+ RowIterator::new(file, first..last)
+ }
}
pub struct RowIterator<R: AsRow> {
- file: usize,
+ file: &'static File,
rows: std::ops::Range<usize>,
phantom: std::marker::PhantomData<R>,
}
impl<R: AsRow> RowIterator<R> {
- pub fn new(file: usize, rows: std::ops::Range<usize>) -> Self {
+ pub fn new(file: &'static File, rows: std::ops::Range<usize>) -> Self {
Self { file, rows, phantom: std::marker::PhantomData }
}
}
@@ -48,44 +140,26 @@ impl<R: AsRow> Iterator for RowIterator<R> {
type Item = R;
fn next(&mut self) -> Option<Self::Item> {
- self.rows.next().map(|row| R::from_row(Row::new(row, self.file)))
+ self.rows.next().map(|row| R::from_row(Row::new(self.file, row)))
}
}
-macro_rules! tables {
- ($(($name:ident, $table:literal))+) => {
- $(
- #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
- pub struct $name(pub(crate) Row);
- impl AsRow for $name {
- const TABLE: usize = $table;
- fn to_row(&self) -> Row {
- self.0
- }
- fn from_row(row: Row) -> Self {
- $name(row)
- }
- }
- )*
-};
+pub trait HasAttributes {
+ fn attributes(&self) -> RowIterator<Attribute>;
+ fn find_attribute(&self, name: &str) -> Option<Attribute>;
+ fn has_attribute(&self, name: &str) -> bool;
}
-tables! {
- (Attribute, 1)
- (ClassLayout, 16)
- (Constant, 0)
- (Field, 2)
- (GenericParam, 3)
- (ImplMap, 11)
- (InterfaceImpl, 4)
- (MemberRef, 5)
- (MethodDef, 6)
- (Module, 14)
- (ModuleRef, 12)
- (AssemblyRef, 15)
- (Param, 7)
- (TypeDef, 8)
- (TypeRef, 9)
- (TypeSpec, 10)
- (NestedClass, 13)
+impl<R: AsRow + Into<HasAttribute>> HasAttributes for R {
+ fn attributes(&self) -> RowIterator<Attribute> {
+ self.equal_range(0, Into::<HasAttribute>::into(*self).encode())
+ }
+
+ fn find_attribute(&self, name: &str) -> Option<Attribute> {
+ self.attributes().find(|attribute| attribute.name() == name)
+ }
+
+ fn has_attribute(&self, name: &str) -> bool {
+ self.find_attribute(name).is_some()
+ }
}
diff --git a/vendor/windows-metadata/src/file/table.rs b/vendor/windows-metadata/src/table.rs
index af9599c31..fd34b50b4 100644
--- a/vendor/windows-metadata/src/file/table.rs
+++ b/vendor/windows-metadata/src/table.rs
@@ -1,3 +1,5 @@
+use super::*;
+
#[derive(Default)]
pub struct Table {
pub offset: usize,
@@ -6,12 +8,6 @@ pub struct Table {
pub columns: [Column; 6],
}
-#[derive(Default)]
-pub struct Column {
- pub offset: usize,
- pub width: usize,
-}
-
impl Table {
pub fn index_width(&self) -> usize {
if self.len < (1 << 16) {
@@ -49,9 +45,3 @@ impl Table {
}
}
}
-
-impl Column {
- fn new(offset: usize, width: usize) -> Self {
- Self { offset, width }
- }
-}
diff --git a/vendor/windows-metadata/src/tables.rs b/vendor/windows-metadata/src/tables.rs
new file mode 100644
index 000000000..d7e3ad608
--- /dev/null
+++ b/vendor/windows-metadata/src/tables.rs
@@ -0,0 +1,420 @@
+use super::*;
+
+macro_rules! tables {
+ ($(($name:ident, $table:literal))+) => {
+ $(
+ #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
+ pub struct $name(pub Row);
+ impl AsRow for $name {
+ const TABLE: usize = $table;
+ fn to_row(&self) -> Row {
+ self.0
+ }
+ fn from_row(row: Row) -> Self {
+ $name(row)
+ }
+ }
+ )*
+ };
+}
+
+tables! {
+ (AssemblyRef, 15)
+ (Attribute, 1)
+ (ClassLayout, 16)
+ (Constant, 0)
+ (Field, 2)
+ (GenericParam, 3)
+ (ImplMap, 11)
+ (InterfaceImpl, 4)
+ (MemberRef, 5)
+ (MethodDef, 6)
+ (Module, 14)
+ (ModuleRef, 12)
+ (NestedClass, 13)
+ (Param, 7)
+ (TypeDef, 8)
+ (TypeRef, 9)
+ (TypeSpec, 10)
+}
+
+impl Attribute {
+ pub fn parent(&self) -> HasAttribute {
+ self.decode(0)
+ }
+
+ pub fn ty(&self) -> AttributeType {
+ self.decode(1)
+ }
+
+ pub fn name(&self) -> &'static str {
+ let AttributeType::MemberRef(ctor) = self.ty();
+ let MemberRefParent::TypeRef(ty) = ctor.parent();
+ ty.name()
+ }
+
+ pub fn type_name(&self) -> TypeName {
+ let AttributeType::MemberRef(ctor) = self.ty();
+ let MemberRefParent::TypeRef(ty) = ctor.parent();
+ ty.type_name()
+ }
+
+ pub fn args(&self) -> Vec<(&'static str, Value)> {
+ let AttributeType::MemberRef(member) = self.ty();
+ let mut sig = member.blob(2);
+ let mut values = self.blob(2);
+ let _prolog = values.read_u16();
+ let _this_and_gen_param_count = sig.read_usize();
+ let fixed_arg_count = sig.read_usize();
+ let _ret_type = sig.read_usize();
+ let mut args = Vec::with_capacity(fixed_arg_count);
+ let reader = self.reader();
+
+ for _ in 0..fixed_arg_count {
+ let arg = match reader.type_from_blob(&mut sig, None, &[]) {
+ Type::Bool => Value::Bool(values.read_bool()),
+ Type::I8 => Value::I8(values.read_i8()),
+ Type::U8 => Value::U8(values.read_u8()),
+ Type::I16 => Value::I16(values.read_i16()),
+ Type::U16 => Value::U16(values.read_u16()),
+ Type::I32 => Value::I32(values.read_i32()),
+ Type::U32 => Value::U32(values.read_u32()),
+ Type::I64 => Value::I64(values.read_i64()),
+ Type::U64 => Value::U64(values.read_u64()),
+ Type::String => Value::String(values.read_str().to_string()),
+ Type::Type => Value::TypeName(TypeName::parse(values.read_str())),
+ Type::TypeDef(def, _) => Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type()))),
+ rest => unimplemented!("{rest:?}"),
+ };
+
+ args.push(("", arg));
+ }
+
+ let named_arg_count = values.read_u16();
+ args.reserve(named_arg_count as usize);
+
+ for _ in 0..named_arg_count {
+ let _id = values.read_u8();
+ let arg_type = values.read_u8();
+ let mut name = values.read_str();
+ let arg = match arg_type {
+ ELEMENT_TYPE_BOOLEAN => Value::Bool(values.read_bool()),
+ ELEMENT_TYPE_I2 => Value::I16(values.read_i16()),
+ ELEMENT_TYPE_I4 => Value::I32(values.read_i32()),
+ ELEMENT_TYPE_U4 => Value::U32(values.read_u32()),
+ ELEMENT_TYPE_STRING => Value::String(values.read_str().to_string()),
+ 0x50 => Value::TypeName(TypeName::parse(values.read_str())),
+ 0x55 => {
+ let type_name = TypeName::parse(name);
+ let def = reader.get_type_def(type_name.namespace, type_name.name).next().expect("Type not found");
+ name = values.read_str();
+ Value::EnumDef(def, Box::new(values.read_integer(def.underlying_type())))
+ }
+ rest => unimplemented!("{rest:?}"),
+ };
+ args.push((name, arg));
+ }
+
+ debug_assert_eq!(sig.slice.len(), 0);
+ debug_assert_eq!(values.slice.len(), 0);
+
+ args
+ }
+}
+
+impl ClassLayout {
+ pub fn packing_size(&self) -> usize {
+ self.usize(0)
+ }
+}
+
+impl Constant {
+ pub fn ty(&self) -> Type {
+ Type::from_code(self.usize(0)).expect("Constant type not found")
+ }
+
+ pub fn value(&self) -> Value {
+ let mut blob = self.blob(2);
+
+ match self.ty() {
+ Type::I8 => Value::I8(blob.read_i8()),
+ Type::U8 => Value::U8(blob.read_u8()),
+ Type::I16 => Value::I16(blob.read_i16()),
+ Type::U16 => Value::U16(blob.read_u16()),
+ Type::I32 => Value::I32(blob.read_i32()),
+ Type::U32 => Value::U32(blob.read_u32()),
+ Type::I64 => Value::I64(blob.read_i64()),
+ Type::U64 => Value::U64(blob.read_u64()),
+ Type::F32 => Value::F32(blob.read_f32()),
+ Type::F64 => Value::F64(blob.read_f64()),
+ Type::String => Value::String(blob.read_string()),
+ rest => unimplemented!("{rest:?}"),
+ }
+ }
+}
+
+impl Field {
+ pub fn flags(&self) -> FieldAttributes {
+ FieldAttributes(self.usize(0) as u16)
+ }
+
+ pub fn name(&self) -> &'static str {
+ self.str(1)
+ }
+
+ pub fn constant(&self) -> Option<Constant> {
+ self.equal_range(1, HasConstant::Field(*self).encode()).next()
+ }
+
+ // TODO: enclosing craziness is only needed for nested structs - get rid of those in riddle and this goes away.
+ pub fn ty(&self, enclosing: Option<TypeDef>) -> Type {
+ let mut blob = self.blob(2);
+ blob.read_usize();
+ blob.read_modifiers();
+ let def = self.reader().type_from_blob(&mut blob, enclosing, &[]);
+
+ if self.has_attribute("ConstAttribute") {
+ def.to_const_type().to_const_ptr()
+ } else {
+ def
+ }
+ }
+}
+
+impl GenericParam {
+ pub fn number(&self) -> u16 {
+ self.usize(0) as u16
+ }
+
+ pub fn name(&self) -> &'static str {
+ self.str(3)
+ }
+}
+
+impl ImplMap {
+ pub fn flags(&self) -> PInvokeAttributes {
+ PInvokeAttributes(self.usize(0))
+ }
+
+ pub fn scope(&self) -> ModuleRef {
+ ModuleRef(self.row(3))
+ }
+
+ pub fn import_name(&self) -> &'static str {
+ self.str(2)
+ }
+}
+
+impl InterfaceImpl {
+ pub fn ty(&self, generics: &[Type]) -> Type {
+ self.reader().type_from_ref(self.decode(1), None, generics)
+ }
+}
+
+impl MemberRef {
+ pub fn parent(&self) -> MemberRefParent {
+ self.decode(0)
+ }
+
+ pub fn name(&self) -> &'static str {
+ self.str(1)
+ }
+}
+
+impl MethodDef {
+ pub fn impl_flags(&self) -> MethodImplAttributes {
+ MethodImplAttributes(self.usize(1) as u16)
+ }
+
+ pub fn flags(&self) -> MethodAttributes {
+ MethodAttributes(self.usize(2) as u16)
+ }
+
+ pub fn name(&self) -> &'static str {
+ self.str(3)
+ }
+
+ pub fn params(&self) -> RowIterator<Param> {
+ self.list(5)
+ }
+
+ pub fn impl_map(&self) -> Option<ImplMap> {
+ self.equal_range(1, MemberForwarded::MethodDef(*self).encode()).next()
+ }
+
+ pub fn module_name(&self) -> String {
+ // TODO: riddle should always lower case the module name to avoid allocating here
+ let Some(impl_map) = self.impl_map() else {
+ return String::new();
+ };
+
+ impl_map.scope().name().to_lowercase()
+ }
+
+ pub fn signature(&self, generics: &[Type]) -> MethodDefSig {
+ let reader = self.reader();
+ let mut blob = self.blob(4);
+ let call_flags = MethodCallAttributes(blob.read_usize() as u8);
+ let params = blob.read_usize();
+ let return_type = reader.type_from_blob(&mut blob, None, generics);
+
+ MethodDefSig { call_flags, return_type, params: (0..params).map(|_| reader.type_from_blob(&mut blob, None, generics)).collect() }
+ }
+}
+
+impl ModuleRef {
+ pub fn name(&self) -> &'static str {
+ self.str(0)
+ }
+}
+
+impl NestedClass {
+ pub fn inner(&self) -> TypeDef {
+ TypeDef(self.row(0))
+ }
+
+ pub fn outer(&self) -> TypeDef {
+ TypeDef(self.row(1))
+ }
+}
+
+impl Param {
+ pub fn flags(&self) -> ParamAttributes {
+ ParamAttributes(self.usize(0) as u16)
+ }
+
+ pub fn sequence(&self) -> u16 {
+ self.usize(1) as u16
+ }
+
+ pub fn name(&self) -> &'static str {
+ self.str(2)
+ }
+}
+
+impl TypeDef {
+ pub fn flags(&self) -> TypeAttributes {
+ TypeAttributes(self.usize(0) as u32)
+ }
+
+ pub fn name(&self) -> &'static str {
+ trim_tick(self.str(1))
+ }
+
+ pub fn namespace(&self) -> &'static str {
+ self.str(2)
+ }
+
+ pub fn type_name(&self) -> TypeName {
+ TypeName::new(self.namespace(), self.name())
+ }
+
+ pub fn extends(&self) -> Option<TypeName> {
+ let extends = self.usize(3);
+
+ if extends == 0 {
+ return None;
+ }
+
+ Some(TypeDefOrRef::decode(self.file(), extends).type_name())
+ }
+
+ pub fn methods(&self) -> RowIterator<MethodDef> {
+ self.list(5)
+ }
+
+ pub fn fields(&self) -> RowIterator<Field> {
+ self.list(4)
+ }
+
+ pub fn generics(&self) -> RowIterator<GenericParam> {
+ self.equal_range(2, TypeOrMethodDef::TypeDef(*self).encode())
+ }
+
+ pub fn interface_impls(&self) -> RowIterator<InterfaceImpl> {
+ self.equal_range(0, self.index() + 1)
+ }
+
+ pub fn enclosing_type(&self) -> Option<TypeDef> {
+ self.equal_range::<NestedClass>(0, self.index() + 1).next().map(|row| TypeDef(row.row(1)))
+ }
+
+ pub fn class_layout(&self) -> Option<ClassLayout> {
+ self.equal_range(2, self.index() + 1).next()
+ }
+
+ pub fn underlying_type(&self) -> Type {
+ let field = self.fields().next().expect("Field not found");
+ if let Some(constant) = field.constant() {
+ constant.ty()
+ } else {
+ field.ty(Some(*self))
+ }
+ }
+
+ pub fn kind(&self) -> TypeKind {
+ match self.extends() {
+ None => TypeKind::Interface,
+ Some(TypeName::Enum) => TypeKind::Enum,
+ Some(TypeName::Delegate) => TypeKind::Delegate,
+ Some(TypeName::Struct) => TypeKind::Struct,
+ Some(_) => TypeKind::Class,
+ }
+ }
+
+ pub fn size(&self) -> usize {
+ match self.kind() {
+ TypeKind::Struct => {
+ if self.flags().contains(TypeAttributes::ExplicitLayout) {
+ self.fields().map(|field| field.ty(Some(*self)).size()).max().unwrap_or(1)
+ } else {
+ let mut sum = 0;
+ for field in self.fields() {
+ let ty = field.ty(Some(*self));
+ let size = ty.size();
+ let align = ty.align();
+ sum = (sum + (align - 1)) & !(align - 1);
+ sum += size;
+ }
+ sum
+ }
+ }
+ TypeKind::Enum => self.underlying_type().size(),
+ _ => 4,
+ }
+ }
+
+ pub fn align(&self) -> usize {
+ match self.kind() {
+ TypeKind::Struct => self.fields().map(|field| field.ty(Some(*self)).align()).max().unwrap_or(1),
+ TypeKind::Enum => self.underlying_type().align(),
+ _ => 4,
+ }
+ }
+}
+
+impl TypeRef {
+ pub fn name(&self) -> &'static str {
+ trim_tick(self.str(1))
+ }
+
+ pub fn namespace(&self) -> &'static str {
+ self.str(2)
+ }
+
+ pub fn type_name(&self) -> TypeName {
+ TypeName::new(self.namespace(), self.name())
+ }
+
+ pub fn resolution_scope(&self) -> ResolutionScope {
+ self.decode(0)
+ }
+}
+
+fn trim_tick(name: &str) -> &str {
+ if name.as_bytes().iter().rev().nth(1) == Some(&b'`') {
+ &name[..name.len() - 2]
+ } else {
+ name
+ }
+}
diff --git a/vendor/windows-metadata/src/type.rs b/vendor/windows-metadata/src/type.rs
index b62faff78..5c2c24eb6 100644
--- a/vendor/windows-metadata/src/type.rs
+++ b/vendor/windows-metadata/src/type.rs
@@ -1,6 +1,6 @@
use super::*;
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
pub enum Type {
// Primitives in ECMA-335
Void,
@@ -23,12 +23,10 @@ pub enum Type {
GUID, // Both Win32 and WinRT agree that this is represented by System.Guid
String, // TODO: Win32 should use System.String when referring to an HSTRING
IInspectable, // TODO: Win32 should use System.Object when referring to an IInspectable
-
- // Meta-type indicating type name in attribute blob.
- TypeName,
+ Type, // System.Type is needed since WinRT attribute use this as a parameter type.
// Regular ECMA-335 types that map to metadata
- TypeRef(TypeDefOrRef), // Note: this ought to be a TypeName but that would require Type to have a lifetime reference.
+ TypeRef(TypeName),
GenericParam(GenericParam),
TypeDef(TypeDef, Vec<Self>),
@@ -176,4 +174,29 @@ impl Type {
_ => false,
}
}
+
+ pub fn size(&self) -> usize {
+ match self {
+ Type::I8 | Type::U8 => 1,
+ Type::I16 | Type::U16 => 2,
+ Type::I64 | Type::U64 | Type::F64 => 8,
+ Type::GUID => 16,
+ Type::TypeDef(def, _) => def.size(),
+ Type::Win32Array(ty, len) => ty.size() * len,
+ Type::PrimitiveOrEnum(ty, _) => ty.size(),
+ _ => 4,
+ }
+ }
+
+ pub fn align(&self) -> usize {
+ match self {
+ Type::I8 | Type::U8 => 1,
+ Type::I16 | Type::U16 => 2,
+ Type::I64 | Type::U64 | Type::F64 => 8,
+ Type::GUID => 4,
+ Type::TypeDef(def, _) => def.align(),
+ Type::Win32Array(ty, len) => ty.align() * len,
+ _ => 4,
+ }
+ }
}
diff --git a/vendor/windows-metadata/src/type_name.rs b/vendor/windows-metadata/src/type_name.rs
index 750d58c3e..431e0f3f9 100644
--- a/vendor/windows-metadata/src/type_name.rs
+++ b/vendor/windows-metadata/src/type_name.rs
@@ -1,12 +1,12 @@
#![allow(non_upper_case_globals)]
-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub struct TypeName<'a> {
- pub namespace: &'a str,
- pub name: &'a str,
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
+pub struct TypeName {
+ pub namespace: &'static str,
+ pub name: &'static str,
}
-impl<'a> TypeName<'a> {
+impl TypeName {
pub const Enum: Self = Self::from_const("System", "Enum");
pub const Delegate: Self = Self::from_const("System", "MulticastDelegate");
pub const Struct: Self = Self::from_const("System", "ValueType");
@@ -30,7 +30,6 @@ impl<'a> TypeName<'a> {
pub const IVectorView: Self = Self::from_const("Windows.Foundation.Collections", "IVectorView");
pub const IVector: Self = Self::from_const("Windows.Foundation.Collections", "IVector");
- pub const NTSTATUS: Self = Self::from_const("Windows.Win32.Foundation", "NTSTATUS");
pub const PWSTR: Self = Self::from_const("Windows.Win32.Foundation", "PWSTR");
pub const PSTR: Self = Self::from_const("Windows.Win32.Foundation", "PSTR");
pub const BSTR: Self = Self::from_const("Windows.Win32.Foundation", "BSTR");
@@ -52,17 +51,17 @@ impl<'a> TypeName<'a> {
Self { namespace, name }
}
- pub fn new(namespace: &'a str, name: &'a str) -> Self {
- Self { namespace, name: crate::trim_tick(name) }
+ pub fn new(namespace: &'static str, name: &'static str) -> Self {
+ Self { namespace, name }
}
- pub fn parse(full_name: &'a str) -> Self {
+ pub fn parse(full_name: &'static str) -> Self {
let index = full_name.rfind('.').expect("Expected full name separated with `.`");
- Self { namespace: &full_name[0..index], name: &full_name[index + 1..] }
+ Self::new(&full_name[0..index], &full_name[index + 1..])
}
}
-impl<'a> std::fmt::Display for TypeName<'a> {
+impl std::fmt::Display for TypeName {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, "{}.{}", self.namespace, self.name)
}