summaryrefslogtreecommitdiffstats
path: root/vendor/windows-metadata/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/windows-metadata/src')
-rw-r--r--vendor/windows-metadata/src/attributes.rs117
-rw-r--r--vendor/windows-metadata/src/blob.rs (renamed from vendor/windows-metadata/src/reader/blob.rs)40
-rw-r--r--vendor/windows-metadata/src/codes.rs (renamed from vendor/windows-metadata/src/reader/codes.rs)104
-rw-r--r--vendor/windows-metadata/src/file/mod.rs338
-rw-r--r--vendor/windows-metadata/src/file/reader.rs359
-rw-r--r--vendor/windows-metadata/src/file/table.rs57
-rw-r--r--vendor/windows-metadata/src/file/view.rs55
-rw-r--r--vendor/windows-metadata/src/filter.rs (renamed from vendor/windows-metadata/src/reader/filter.rs)12
-rw-r--r--vendor/windows-metadata/src/guid.rs (renamed from vendor/windows-metadata/src/reader/guid.rs)6
-rw-r--r--vendor/windows-metadata/src/imp/bindings.rs (renamed from vendor/windows-metadata/src/bindings.rs)178
-rw-r--r--vendor/windows-metadata/src/imp/mod.rs (renamed from vendor/windows-metadata/src/imp.rs)3
-rw-r--r--vendor/windows-metadata/src/lib.rs480
-rw-r--r--vendor/windows-metadata/src/reader/file.rs537
-rw-r--r--vendor/windows-metadata/src/reader/mod.rs1833
-rw-r--r--vendor/windows-metadata/src/reader/row.rs15
-rw-r--r--vendor/windows-metadata/src/reader/tree.rs31
-rw-r--r--vendor/windows-metadata/src/reader/type.rs152
-rw-r--r--vendor/windows-metadata/src/row.rs91
-rw-r--r--vendor/windows-metadata/src/type.rs179
-rw-r--r--vendor/windows-metadata/src/type_name.rs (renamed from vendor/windows-metadata/src/reader/type_name.rs)16
-rw-r--r--vendor/windows-metadata/src/writer/imp/blobs.rs60
-rw-r--r--vendor/windows-metadata/src/writer/imp/codes.rs94
-rw-r--r--vendor/windows-metadata/src/writer/imp/definitions.rs43
-rw-r--r--vendor/windows-metadata/src/writer/imp/file.rs138
-rw-r--r--vendor/windows-metadata/src/writer/imp/mod.rs408
-rw-r--r--vendor/windows-metadata/src/writer/imp/references.rs36
-rw-r--r--vendor/windows-metadata/src/writer/imp/strings.rs46
-rw-r--r--vendor/windows-metadata/src/writer/imp/tables.rs287
-rw-r--r--vendor/windows-metadata/src/writer/mod.rs95
29 files changed, 1861 insertions, 3949 deletions
diff --git a/vendor/windows-metadata/src/attributes.rs b/vendor/windows-metadata/src/attributes.rs
index 40b6326fe..789214739 100644
--- a/vendor/windows-metadata/src/attributes.rs
+++ b/vendor/windows-metadata/src/attributes.rs
@@ -1,55 +1,108 @@
-use super::*;
+#![allow(non_upper_case_globals)]
+
+macro_rules! flags {
+ ($name:ident, $size:ty) => {
+ #[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
+ pub struct $name(pub $size);
+ impl $name {
+ pub fn contains(&self, contains: Self) -> bool {
+ *self & contains == contains
+ }
+ }
+ impl std::ops::BitOr for $name {
+ type Output = Self;
+ fn bitor(self, other: Self) -> Self {
+ Self(self.0 | other.0)
+ }
+ }
+ impl std::ops::BitAnd for $name {
+ type Output = Self;
+ fn bitand(self, other: Self) -> Self {
+ Self(self.0 & other.0)
+ }
+ }
+ impl std::ops::BitOrAssign for $name {
+ fn bitor_assign(&mut self, other: Self) {
+ self.0.bitor_assign(other.0)
+ }
+ }
+ impl std::ops::BitAndAssign for $name {
+ fn bitand_assign(&mut self, other: Self) {
+ self.0.bitand_assign(other.0)
+ }
+ }
+ impl std::ops::Not for $name {
+ type Output = Self;
+ fn not(self) -> Self {
+ Self(self.0.not())
+ }
+ }
+ };
+}
flags!(FieldAttributes, u16);
impl FieldAttributes {
- pub const PRIVATE: Self = Self(0x1);
- pub const PUBLIC: Self = Self(0x6);
- pub const LITERAL: Self = Self(0x40);
- pub const STATIC: Self = Self(0x10);
- pub const SPECIAL: Self = Self(0x200);
- pub const RUNTIME_SPECIAL: Self = Self(0x400);
- pub const HAS_DEFAULT: Self = Self(0x8000);
+ pub const Private: Self = Self(0x1);
+ pub const Public: Self = Self(0x6);
+ pub const Literal: Self = Self(0x40);
+ pub const Static: Self = Self(0x10);
+ pub const SpecialName: Self = Self(0x200);
+ pub const RTSpecialName: Self = Self(0x400);
+ pub const HasDefault: Self = Self(0x8000);
}
flags!(MethodAttributes, u16);
impl MethodAttributes {
- pub const ABSTRACT: Self = Self(0x400);
- pub const HIDE_BY_SIG: Self = Self(0x80);
- pub const NEW_SLOT: Self = Self(0x100);
- pub const PUBLIC: Self = Self(0x6);
- pub const SPECIAL: Self = Self(0x800);
- pub const VIRTUAL: Self = Self(0x40);
+ pub const Abstract: Self = Self(0x400);
+ pub const HideBySig: Self = Self(0x80);
+ pub const NewSlot: Self = Self(0x100);
+ pub const Public: Self = Self(0x6);
+ pub const SpecialName: Self = Self(0x800);
+ pub const Virtual: Self = Self(0x40);
}
-flags!(MethodImplAttributes, usize);
+flags!(MethodImplAttributes, u16);
impl MethodImplAttributes {
- pub const PRESERVE_SIG: Self = Self(0x80);
+ pub const PreserveSig: Self = Self(0x80);
+}
+
+// These are not really ECMA-335 attributes but instead the flags found in the method signature.
+flags!(MethodCallAttributes, u8);
+impl MethodCallAttributes {
+ pub const HASTHIS: Self = Self(0x20);
+ pub const VARARG: Self = Self(0x05);
}
flags!(ParamAttributes, u16);
impl ParamAttributes {
- pub const INPUT: Self = Self(0x1);
- pub const OUTPUT: Self = Self(0x2);
- pub const OPTIONAL: Self = Self(0x10);
+ pub const In: Self = Self(0x1);
+ pub const Out: Self = Self(0x2);
+ pub const Optional: Self = Self(0x10);
}
flags!(PInvokeAttributes, usize);
impl PInvokeAttributes {
- pub const LAST_ERROR: Self = Self(0x40);
- pub const CONV_PLATFORM: Self = Self(0x100);
- pub const CONV_CDECL: Self = Self(0x200);
- pub const CONV_STDCALL: Self = Self(0x300);
- pub const CONV_THISCALL: Self = Self(0x400);
- pub const CONV_FASTCALL: Self = Self(0x500);
+ pub const SupportsLastError: Self = Self(0x40);
+ pub const CallConvPlatformapi: Self = Self(0x100);
+ pub const CallConvCdecl: Self = Self(0x200);
+ pub const CallConvStdcall: Self = Self(0x300);
+ pub const CallConvThiscall: Self = Self(0x400);
+ pub const CallConvFastcall: Self = Self(0x500);
}
flags!(TypeAttributes, u32);
impl TypeAttributes {
- pub const PUBLIC: Self = Self(0x1);
- pub const EXPLICIT_LAYOUT: Self = Self(0x10);
- pub const ABSTRACT: Self = Self(0x80);
- pub const SEALED: Self = Self(0x100);
- pub const WINRT: Self = Self(0x4000);
- pub const INTERFACE: Self = Self(0x20);
- pub const SEQUENTIAL_LAYOUT: Self = Self(0x8);
+ pub const Public: Self = Self(0x1);
+ pub const ExplicitLayout: Self = Self(0x10);
+ pub const Abstract: Self = Self(0x80);
+ pub const Sealed: Self = Self(0x100);
+ pub const WindowsRuntime: Self = Self(0x4000);
+ pub const Interface: Self = Self(0x20);
+ pub const SequentialLayout: Self = Self(0x8);
+ pub const Import: Self = Self(0x1000);
+}
+
+flags!(AssemblyFlags, u32);
+impl AssemblyFlags {
+ pub const WindowsRuntime: Self = Self(0x200);
}
diff --git a/vendor/windows-metadata/src/reader/blob.rs b/vendor/windows-metadata/src/blob.rs
index b7d4880d0..a54336db1 100644
--- a/vendor/windows-metadata/src/reader/blob.rs
+++ b/vendor/windows-metadata/src/blob.rs
@@ -1,5 +1,4 @@
use super::*;
-use std::convert::*;
pub struct Blob<'a> {
pub file: usize,
@@ -18,6 +17,7 @@ impl<'a> Blob<'a> {
pub fn new(file: usize, slice: &'a [u8]) -> Self {
Self { file, slice }
}
+
pub fn peek_usize(&self) -> (usize, usize) {
if self[0] & 0x80 == 0 {
(self[0] as usize, 1)
@@ -27,11 +27,13 @@ impl<'a> Blob<'a> {
((((self[0] & 0x1F) as usize) << 24) | (self[1] as usize) << 16 | (self[2] as usize) << 8 | self[3] as usize, 4)
}
}
+
pub fn read_usize(&mut self) -> usize {
let (value, offset) = self.peek_usize();
self.offset(offset);
value
}
+
pub fn read_expected(&mut self, expected: usize) -> bool {
let (value, offset) = self.peek_usize();
if value == expected {
@@ -41,11 +43,12 @@ impl<'a> Blob<'a> {
false
}
}
+
pub fn read_modifiers(&mut self) -> Vec<TypeDefOrRef> {
let mut mods = vec![];
loop {
let (value, offset) = self.peek_usize();
- if value != 32 && value != 31 {
+ if value != ELEMENT_TYPE_CMOD_OPT as usize && value != ELEMENT_TYPE_CMOD_REQD as usize {
break;
} else {
self.offset(offset);
@@ -54,12 +57,14 @@ impl<'a> Blob<'a> {
}
mods
}
+
pub fn read_str(&mut self) -> &str {
let len = self.read_usize();
let value = unsafe { std::str::from_utf8_unchecked(&self.slice[..len]) };
self.offset(len);
value
}
+
pub fn read_string(self) -> String {
let slice = self.slice;
if slice.as_ptr().align_offset(std::mem::align_of::<u16>()) > 0 {
@@ -70,6 +75,7 @@ impl<'a> Blob<'a> {
String::from_utf16_lossy(slice)
}
}
+
pub fn read_bool(&mut self) -> bool {
// A bool is specified as "a single byte with value 0 (false) or 1 (true)".
match self.read_u8() {
@@ -78,69 +84,81 @@ impl<'a> Blob<'a> {
_ => panic!("Illegal bool value"),
}
}
+
pub fn read_i8(&mut self) -> i8 {
let value = i8::from_le_bytes(self[..1].try_into().unwrap());
self.offset(1);
value
}
+
pub fn read_u8(&mut self) -> u8 {
let value = u8::from_le_bytes(self[..1].try_into().unwrap());
self.offset(1);
value
}
+
pub fn read_i16(&mut self) -> i16 {
let value = i16::from_le_bytes(self[..2].try_into().unwrap());
self.offset(2);
value
}
+
pub fn read_u16(&mut self) -> u16 {
let value = u16::from_le_bytes(self[..2].try_into().unwrap());
self.offset(2);
value
}
+
pub fn read_i32(&mut self) -> i32 {
let value = i32::from_le_bytes(self[..4].try_into().unwrap());
self.offset(4);
value
}
+
pub fn read_u32(&mut self) -> u32 {
let value = u32::from_le_bytes(self[..4].try_into().unwrap());
self.offset(4);
value
}
+
pub fn read_i64(&mut self) -> i64 {
let value = i64::from_le_bytes(self[..8].try_into().unwrap());
self.offset(8);
value
}
+
pub fn read_u64(&mut self) -> u64 {
let value = u64::from_le_bytes(self[..8].try_into().unwrap());
self.offset(8);
value
}
+
pub fn read_f32(&mut self) -> f32 {
let value = f32::from_le_bytes(self[..4].try_into().unwrap());
self.offset(4);
value
}
+
pub fn read_f64(&mut self) -> f64 {
let value = f64::from_le_bytes(self[..8].try_into().unwrap());
self.offset(8);
value
}
- pub fn read_integer(&mut self, ty: Type) -> Integer {
+
+ pub fn read_integer(&mut self, ty: Type) -> Value {
match ty {
- Type::I8 => Integer::I8(self.read_i8()),
- Type::U8 => Integer::U8(self.read_u8()),
- Type::I16 => Integer::I16(self.read_i16()),
- Type::U16 => Integer::U16(self.read_u16()),
- Type::I32 => Integer::I32(self.read_i32()),
- Type::U32 => Integer::U32(self.read_u32()),
- Type::I64 => Integer::I64(self.read_i64()),
- Type::U64 => Integer::U64(self.read_u64()),
+ Type::I8 => Value::I8(self.read_i8()),
+ Type::U8 => Value::U8(self.read_u8()),
+ Type::I16 => Value::I16(self.read_i16()),
+ Type::U16 => Value::U16(self.read_u16()),
+ Type::I32 => Value::I32(self.read_i32()),
+ Type::U32 => Value::U32(self.read_u32()),
+ Type::I64 => Value::I64(self.read_i64()),
+ Type::U64 => Value::U64(self.read_u64()),
_ => panic!("Type is not an integer"),
}
}
+
fn offset(&mut self, offset: usize) {
self.slice = &self.slice[offset..];
}
diff --git a/vendor/windows-metadata/src/reader/codes.rs b/vendor/windows-metadata/src/codes.rs
index a6cfa4885..d19f6e476 100644
--- a/vendor/windows-metadata/src/reader/codes.rs
+++ b/vendor/windows-metadata/src/codes.rs
@@ -12,8 +12,8 @@ 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, TABLE_MEMBERREF, file))),
- _ => unimplemented!(),
+ 3 => Self::MemberRef(MemberRef(Row::new(row, file))),
+ rest => unimplemented!("{rest:?}"),
}
}
}
@@ -32,7 +32,7 @@ pub enum HasAttribute {
impl HasAttribute {
pub fn encode(&self) -> usize {
- (match self {
+ 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,
@@ -42,7 +42,53 @@ impl HasAttribute {
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,
- }) as _
+ }
+ }
+}
+
+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)
}
}
@@ -53,9 +99,9 @@ pub enum HasConstant {
impl HasConstant {
pub fn encode(&self) -> usize {
- (match self {
+ match self {
Self::Field(row) => (row.0.row + 1) << 2,
- }) as _
+ }
}
}
@@ -66,9 +112,9 @@ pub enum MemberForwarded {
impl MemberForwarded {
pub fn encode(&self) -> usize {
- (match self {
+ match self {
Self::MethodDef(value) => ((value.0.row + 1) << 1) | 1,
- }) as _
+ }
}
}
@@ -80,15 +126,14 @@ 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, TABLE_TYPEREF, file))),
- _ => unimplemented!(),
+ 1 => Self::TypeRef(TypeRef(Row::new(row, file))),
+ rest => unimplemented!("{rest:?}"),
}
}
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum TypeDefOrRef {
- None,
TypeDef(TypeDef),
TypeRef(TypeRef),
TypeSpec(TypeSpec),
@@ -96,15 +141,12 @@ pub enum TypeDefOrRef {
impl Decode for TypeDefOrRef {
fn decode(file: usize, code: usize) -> Self {
- if code == 0 {
- return Self::None;
- }
let (kind, row) = (code & ((1 << 2) - 1), (code >> 2) - 1);
match kind {
- 0 => Self::TypeDef(TypeDef(Row::new(row, TABLE_TYPEDEF, file))),
- 1 => Self::TypeRef(TypeRef(Row::new(row, TABLE_TYPEREF, file))),
- 2 => Self::TypeSpec(TypeSpec(Row::new(row, TABLE_TYPESPEC, file))),
- _ => unimplemented!(),
+ 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:?}"),
}
}
}
@@ -115,8 +157,28 @@ pub enum TypeOrMethodDef {
impl TypeOrMethodDef {
pub fn encode(&self) -> usize {
- (match self {
+ match self {
Self::TypeDef(value) => (value.0.row + 1) << 1,
- }) as _
+ }
+ }
+}
+
+pub enum ResolutionScope {
+ Module(Module),
+ ModuleRef(ModuleRef),
+ AssemblyRef(AssemblyRef),
+ TypeRef(TypeRef),
+}
+
+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))),
+ rest => unimplemented!("{rest:?}"),
+ }
}
}
diff --git a/vendor/windows-metadata/src/file/mod.rs b/vendor/windows-metadata/src/file/mod.rs
new file mode 100644
index 000000000..41a6db920
--- /dev/null
+++ b/vendor/windows-metadata/src/file/mod.rs
@@ -0,0 +1,338 @@
+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],
+}
+
+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 dos = result.bytes.view_as::<IMAGE_DOS_HEADER>(0)?;
+
+ if dos.e_magic != IMAGE_DOS_SIGNATURE || result.bytes.copy_as::<u32>(dos.e_lfanew as usize)? != IMAGE_NT_SIGNATURE {
+ return Err(());
+ }
+
+ let file_offset = dos.e_lfanew as usize + std::mem::size_of::<u32>();
+ let file = result.bytes.view_as::<IMAGE_FILE_HEADER>(file_offset)?;
+
+ let optional_offset = file_offset + std::mem::size_of::<IMAGE_FILE_HEADER>();
+
+ let (com_virtual_address, sections) = match result.bytes.copy_as::<u16>(optional_offset)? {
+ IMAGE_NT_OPTIONAL_HDR32_MAGIC => {
+ let optional = result.bytes.view_as::<IMAGE_OPTIONAL_HEADER32>(optional_offset)?;
+ (optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(optional_offset + std::mem::size_of::<IMAGE_OPTIONAL_HEADER32>(), file.NumberOfSections as usize)?)
+ }
+ IMAGE_NT_OPTIONAL_HDR64_MAGIC => {
+ let optional = result.bytes.view_as::<IMAGE_OPTIONAL_HEADER64>(optional_offset)?;
+ (optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(optional_offset + std::mem::size_of::<IMAGE_OPTIONAL_HEADER64>(), file.NumberOfSections as usize)?)
+ }
+ _ => return Err(()),
+ };
+
+ let clr = result.bytes.view_as::<IMAGE_COR20_HEADER>(offset_from_rva(section_from_rva(sections, com_virtual_address)?, com_virtual_address))?;
+
+ if clr.cb != std::mem::size_of::<IMAGE_COR20_HEADER>() as u32 {
+ return Err(());
+ }
+
+ let metadata_offset = offset_from_rva(section_from_rva(sections, clr.MetaData.VirtualAddress)?, clr.MetaData.VirtualAddress);
+ let metadata = result.bytes.view_as::<METADATA_HEADER>(metadata_offset)?;
+
+ if metadata.signature != METADATA_SIGNATURE {
+ return Err(());
+ }
+
+ // The METADATA_HEADER struct is not a fixed size so have to offset a little more carefully.
+ let mut view = metadata_offset + metadata.length as usize + 20;
+ let mut tables_data: (usize, usize) = (0, 0);
+
+ for _ in 0..result.bytes.copy_as::<u16>(metadata_offset + metadata.length as usize + 18)? {
+ let stream_offset = result.bytes.copy_as::<u32>(view)? as usize;
+ let stream_len = result.bytes.copy_as::<u32>(view + 4)? as usize;
+ let stream_name = result.bytes.view_as_str(view + 8)?;
+ match stream_name {
+ b"#Strings" => result.strings = metadata_offset + stream_offset,
+ b"#Blob" => result.blobs = metadata_offset + stream_offset,
+ b"#~" => tables_data = (metadata_offset + stream_offset, stream_len),
+ b"#GUID" => {}
+ b"#US" => {}
+ rest => unimplemented!("{rest:?}"),
+ }
+ let mut padding = 4 - stream_name.len() % 4;
+ if padding == 0 {
+ padding = 4;
+ }
+ view += 8 + stream_name.len() + padding;
+ }
+
+ let heap_sizes = result.bytes.copy_as::<u8>(tables_data.0 + 6)?;
+ let string_index_size = if (heap_sizes & 1) == 1 { 4 } else { 2 };
+ let guid_index_size = if (heap_sizes >> 1 & 1) == 1 { 4 } else { 2 };
+ let blob_index_size = if (heap_sizes >> 2 & 1) == 1 { 4 } else { 2 };
+ let valid_bits = result.bytes.copy_as::<u64>(tables_data.0 + 8)?;
+ view = tables_data.0 + 24;
+
+ // These tables are unused by the reader, but needed temporarily to calculate sizes and offsets for subsequent tables.
+ let unused_empty = Table::default();
+ let mut unused_assembly = Table::default();
+ let mut unused_assembly_os = Table::default();
+ let mut unused_assembly_processor = Table::default();
+ let mut unused_assembly_ref_os = Table::default();
+ let mut unused_assembly_ref_processor = Table::default();
+ let mut unused_decl_security = Table::default();
+ let mut unused_event = Table::default();
+ let mut unused_event_map = Table::default();
+ let mut unused_exported_type = Table::default();
+ let mut unused_field_layout = Table::default();
+ let mut unused_field_marshal = Table::default();
+ let mut unused_field_rva = Table::default();
+ let mut unused_file = Table::default();
+ let mut unused_generic_param_constraint = Table::default();
+ let mut unused_manifest_resource = Table::default();
+ let mut unused_method_impl = Table::default();
+ let mut unused_method_semantics = Table::default();
+ let mut unused_method_spec = Table::default();
+ let mut unused_property = Table::default();
+ let mut unused_property_map = Table::default();
+ let mut unused_standalone_sig = Table::default();
+
+ for i in 0..64 {
+ if (valid_bits >> i & 1) == 0 {
+ continue;
+ }
+
+ let len = result.bytes.copy_as::<u32>(view)? as usize;
+ view += 4;
+
+ match i {
+ 0x00 => result.tables[Module::TABLE].len = len,
+ 0x01 => result.tables[TypeRef::TABLE].len = len,
+ 0x02 => result.tables[TypeDef::TABLE].len = len,
+ 0x04 => result.tables[Field::TABLE].len = len,
+ 0x06 => result.tables[MethodDef::TABLE].len = len,
+ 0x08 => result.tables[Param::TABLE].len = len,
+ 0x09 => result.tables[InterfaceImpl::TABLE].len = len,
+ 0x0a => result.tables[MemberRef::TABLE].len = len,
+ 0x0b => result.tables[Constant::TABLE].len = len,
+ 0x0c => result.tables[Attribute::TABLE].len = len,
+ 0x0d => unused_field_marshal.len = len,
+ 0x0e => unused_decl_security.len = len,
+ 0x0f => result.tables[ClassLayout::TABLE].len = len,
+ 0x10 => unused_field_layout.len = len,
+ 0x11 => unused_standalone_sig.len = len,
+ 0x12 => unused_event_map.len = len,
+ 0x14 => unused_event.len = len,
+ 0x15 => unused_property_map.len = len,
+ 0x17 => unused_property.len = len,
+ 0x18 => unused_method_semantics.len = len,
+ 0x19 => unused_method_impl.len = len,
+ 0x1a => result.tables[ModuleRef::TABLE].len = len,
+ 0x1b => result.tables[TypeSpec::TABLE].len = len,
+ 0x1c => result.tables[ImplMap::TABLE].len = len,
+ 0x1d => unused_field_rva.len = len,
+ 0x20 => unused_assembly.len = len,
+ 0x21 => unused_assembly_processor.len = len,
+ 0x22 => unused_assembly_os.len = len,
+ 0x23 => result.tables[AssemblyRef::TABLE].len = len,
+ 0x24 => unused_assembly_ref_processor.len = len,
+ 0x25 => unused_assembly_ref_os.len = len,
+ 0x26 => unused_file.len = len,
+ 0x27 => unused_exported_type.len = len,
+ 0x28 => unused_manifest_resource.len = len,
+ 0x29 => result.tables[NestedClass::TABLE].len = len,
+ 0x2a => result.tables[GenericParam::TABLE].len = len,
+ 0x2b => unused_method_spec.len = len,
+ 0x2c => unused_generic_param_constraint.len = len,
+ _ => unreachable!(),
+ };
+ }
+
+ let tables = &result.tables;
+ let type_def_or_ref = coded_index_size(&[tables[TypeDef::TABLE].len, tables[TypeRef::TABLE].len, tables[TypeSpec::TABLE].len]);
+ let has_constant = coded_index_size(&[tables[Field::TABLE].len, tables[Param::TABLE].len, unused_property.len]);
+ let has_field_marshal = coded_index_size(&[tables[Field::TABLE].len, tables[Param::TABLE].len]);
+ let has_decl_security = coded_index_size(&[tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len, unused_assembly.len]);
+ let member_ref_parent = coded_index_size(&[tables[TypeDef::TABLE].len, tables[TypeRef::TABLE].len, tables[ModuleRef::TABLE].len, tables[MethodDef::TABLE].len, tables[TypeSpec::TABLE].len]);
+ let has_semantics = coded_index_size(&[unused_event.len, unused_property.len]);
+ let method_def_or_ref = coded_index_size(&[tables[MethodDef::TABLE].len, tables[MemberRef::TABLE].len]);
+ let member_forwarded = coded_index_size(&[tables[Field::TABLE].len, tables[MethodDef::TABLE].len]);
+ let implementation = coded_index_size(&[unused_file.len, tables[AssemblyRef::TABLE].len, unused_exported_type.len]);
+ let custom_attribute_type = coded_index_size(&[tables[MethodDef::TABLE].len, tables[MemberRef::TABLE].len, unused_empty.len, unused_empty.len, unused_empty.len]);
+ let resolution_scope = coded_index_size(&[tables[Module::TABLE].len, tables[ModuleRef::TABLE].len, tables[AssemblyRef::TABLE].len, tables[TypeRef::TABLE].len]);
+ let type_or_method_def = coded_index_size(&[tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len]);
+
+ let has_custom_attribute = coded_index_size(&[
+ tables[MethodDef::TABLE].len,
+ tables[Field::TABLE].len,
+ tables[TypeRef::TABLE].len,
+ tables[TypeDef::TABLE].len,
+ tables[Param::TABLE].len,
+ tables[InterfaceImpl::TABLE].len,
+ tables[MemberRef::TABLE].len,
+ tables[Module::TABLE].len,
+ unused_property.len,
+ unused_event.len,
+ unused_standalone_sig.len,
+ tables[ModuleRef::TABLE].len,
+ tables[TypeSpec::TABLE].len,
+ unused_assembly.len,
+ tables[AssemblyRef::TABLE].len,
+ unused_file.len,
+ unused_exported_type.len,
+ unused_manifest_resource.len,
+ tables[GenericParam::TABLE].len,
+ unused_generic_param_constraint.len,
+ unused_method_spec.len,
+ ]);
+
+ unused_assembly.set_columns(4, 8, 4, blob_index_size, string_index_size, string_index_size);
+ unused_assembly_os.set_columns(4, 4, 4, 0, 0, 0);
+ unused_assembly_processor.set_columns(4, 0, 0, 0, 0, 0);
+ result.tables[AssemblyRef::TABLE].set_columns(8, 4, blob_index_size, string_index_size, string_index_size, blob_index_size);
+ unused_assembly_ref_os.set_columns(4, 4, 4, result.tables[AssemblyRef::TABLE].index_width(), 0, 0);
+ unused_assembly_ref_processor.set_columns(4, result.tables[AssemblyRef::TABLE].index_width(), 0, 0, 0, 0);
+ result.tables[ClassLayout::TABLE].set_columns(2, 4, result.tables[TypeDef::TABLE].index_width(), 0, 0, 0);
+ result.tables[Constant::TABLE].set_columns(2, has_constant, blob_index_size, 0, 0, 0);
+ result.tables[Attribute::TABLE].set_columns(has_custom_attribute, custom_attribute_type, blob_index_size, 0, 0, 0);
+ unused_decl_security.set_columns(2, has_decl_security, blob_index_size, 0, 0, 0);
+ unused_event_map.set_columns(result.tables[TypeDef::TABLE].index_width(), unused_event.index_width(), 0, 0, 0, 0);
+ unused_event.set_columns(2, string_index_size, type_def_or_ref, 0, 0, 0);
+ unused_exported_type.set_columns(4, 4, string_index_size, string_index_size, implementation, 0);
+ result.tables[Field::TABLE].set_columns(2, string_index_size, blob_index_size, 0, 0, 0);
+ unused_field_layout.set_columns(4, result.tables[Field::TABLE].index_width(), 0, 0, 0, 0);
+ unused_field_marshal.set_columns(has_field_marshal, blob_index_size, 0, 0, 0, 0);
+ unused_field_rva.set_columns(4, result.tables[Field::TABLE].index_width(), 0, 0, 0, 0);
+ unused_file.set_columns(4, string_index_size, blob_index_size, 0, 0, 0);
+ result.tables[GenericParam::TABLE].set_columns(2, 2, type_or_method_def, string_index_size, 0, 0);
+ unused_generic_param_constraint.set_columns(result.tables[GenericParam::TABLE].index_width(), type_def_or_ref, 0, 0, 0, 0);
+ result.tables[ImplMap::TABLE].set_columns(2, member_forwarded, string_index_size, result.tables[ModuleRef::TABLE].index_width(), 0, 0);
+ result.tables[InterfaceImpl::TABLE].set_columns(result.tables[TypeDef::TABLE].index_width(), type_def_or_ref, 0, 0, 0, 0);
+ unused_manifest_resource.set_columns(4, 4, string_index_size, implementation, 0, 0);
+ result.tables[MemberRef::TABLE].set_columns(member_ref_parent, string_index_size, blob_index_size, 0, 0, 0);
+ result.tables[MethodDef::TABLE].set_columns(4, 2, 2, string_index_size, blob_index_size, result.tables[Param::TABLE].index_width());
+ unused_method_impl.set_columns(result.tables[TypeDef::TABLE].index_width(), method_def_or_ref, method_def_or_ref, 0, 0, 0);
+ unused_method_semantics.set_columns(2, result.tables[MethodDef::TABLE].index_width(), has_semantics, 0, 0, 0);
+ unused_method_spec.set_columns(method_def_or_ref, blob_index_size, 0, 0, 0, 0);
+ result.tables[Module::TABLE].set_columns(2, string_index_size, guid_index_size, guid_index_size, guid_index_size, 0);
+ result.tables[ModuleRef::TABLE].set_columns(string_index_size, 0, 0, 0, 0, 0);
+ result.tables[NestedClass::TABLE].set_columns(result.tables[TypeDef::TABLE].index_width(), result.tables[TypeDef::TABLE].index_width(), 0, 0, 0, 0);
+ result.tables[Param::TABLE].set_columns(2, 2, string_index_size, 0, 0, 0);
+ unused_property.set_columns(2, string_index_size, blob_index_size, 0, 0, 0);
+ unused_property_map.set_columns(result.tables[TypeDef::TABLE].index_width(), unused_property.index_width(), 0, 0, 0, 0);
+ unused_standalone_sig.set_columns(blob_index_size, 0, 0, 0, 0, 0);
+ result.tables[TypeDef::TABLE].set_columns(4, string_index_size, string_index_size, type_def_or_ref, result.tables[Field::TABLE].index_width(), result.tables[MethodDef::TABLE].index_width());
+ result.tables[TypeRef::TABLE].set_columns(resolution_scope, string_index_size, string_index_size, 0, 0, 0);
+ result.tables[TypeSpec::TABLE].set_columns(blob_index_size, 0, 0, 0, 0, 0);
+
+ result.tables[Module::TABLE].set_data(&mut view);
+ result.tables[TypeRef::TABLE].set_data(&mut view);
+ result.tables[TypeDef::TABLE].set_data(&mut view);
+ result.tables[Field::TABLE].set_data(&mut view);
+ result.tables[MethodDef::TABLE].set_data(&mut view);
+ result.tables[Param::TABLE].set_data(&mut view);
+ result.tables[InterfaceImpl::TABLE].set_data(&mut view);
+ result.tables[MemberRef::TABLE].set_data(&mut view);
+ result.tables[Constant::TABLE].set_data(&mut view);
+ result.tables[Attribute::TABLE].set_data(&mut view);
+ unused_field_marshal.set_data(&mut view);
+ unused_decl_security.set_data(&mut view);
+ result.tables[ClassLayout::TABLE].set_data(&mut view);
+ unused_field_layout.set_data(&mut view);
+ unused_standalone_sig.set_data(&mut view);
+ unused_event_map.set_data(&mut view);
+ unused_event.set_data(&mut view);
+ unused_property_map.set_data(&mut view);
+ unused_property.set_data(&mut view);
+ unused_method_semantics.set_data(&mut view);
+ unused_method_impl.set_data(&mut view);
+ result.tables[ModuleRef::TABLE].set_data(&mut view);
+ result.tables[TypeSpec::TABLE].set_data(&mut view);
+ result.tables[ImplMap::TABLE].set_data(&mut view);
+ unused_field_rva.set_data(&mut view);
+ unused_assembly.set_data(&mut view);
+ unused_assembly_processor.set_data(&mut view);
+ unused_assembly_os.set_data(&mut view);
+ result.tables[AssemblyRef::TABLE].set_data(&mut view);
+ unused_assembly_ref_processor.set_data(&mut view);
+ unused_assembly_ref_os.set_data(&mut view);
+ unused_file.set_data(&mut view);
+ unused_exported_type.set_data(&mut view);
+ unused_manifest_resource.set_data(&mut view);
+ result.tables[NestedClass::TABLE].set_data(&mut view);
+ result.tables[GenericParam::TABLE].set_data(&mut view);
+
+ Ok(result)
+ }
+
+ 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;
+ match column.width {
+ 1 => self.bytes.copy_as::<u8>(offset).map_or(0, |v| v as usize),
+ 2 => self.bytes.copy_as::<u16>(offset).map_or(0, |v| v as usize),
+ 4 => self.bytes.copy_as::<u32>(offset).map_or(0, |v| v as usize),
+ _ => self.bytes.copy_as::<u64>(offset).map_or(0, |v| v as usize),
+ }
+ }
+
+ 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;
+ let middle = first + count2;
+ if self.usize(middle, table, column) < value {
+ first = middle + 1;
+ count -= count2 + 1;
+ } else {
+ count = count2;
+ }
+ }
+ first
+ }
+
+ 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;
+ let middle = first + count2;
+ if value < self.usize(middle, table, column) {
+ count = count2
+ } else {
+ first = middle + 1;
+ count -= count2 + 1;
+ }
+ }
+ first
+ }
+
+ pub fn table<R: AsRow>(&self, file: usize) -> RowIterator<R> {
+ RowIterator::new(file, 0..self.tables[R::TABLE].len)
+ }
+}
+
+fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Result<&IMAGE_SECTION_HEADER> {
+ sections.iter().find(|&s| rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize }).ok_or(())
+}
+
+fn offset_from_rva(section: &IMAGE_SECTION_HEADER, rva: u32) -> usize {
+ (rva - section.VirtualAddress + section.PointerToRawData) as usize
+}
diff --git a/vendor/windows-metadata/src/file/reader.rs b/vendor/windows-metadata/src/file/reader.rs
new file mode 100644
index 000000000..571a06d5e
--- /dev/null
+++ b/vendor/windows-metadata/src/file/reader.rs
@@ -0,0 +1,359 @@
+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/table.rs b/vendor/windows-metadata/src/file/table.rs
new file mode 100644
index 000000000..af9599c31
--- /dev/null
+++ b/vendor/windows-metadata/src/file/table.rs
@@ -0,0 +1,57 @@
+#[derive(Default)]
+pub struct Table {
+ pub offset: usize,
+ pub len: usize,
+ pub width: usize,
+ 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) {
+ 2
+ } else {
+ 4
+ }
+ }
+
+ pub fn set_columns(&mut self, a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) {
+ self.width = a + b + c + d + e + f;
+ self.columns[0] = Column::new(0, a);
+ if b != 0 {
+ self.columns[1] = Column::new(a, b);
+ }
+ if c != 0 {
+ self.columns[2] = Column::new(a + b, c);
+ }
+ if d != 0 {
+ self.columns[3] = Column::new(a + b + c, d);
+ }
+ if e != 0 {
+ self.columns[4] = Column::new(a + b + c + d, e);
+ }
+ if f != 0 {
+ self.columns[5] = Column::new(a + b + c + d + e, f);
+ }
+ }
+
+ pub fn set_data(&mut self, offset: &mut usize) {
+ if self.len != 0 {
+ let next = *offset + self.len * self.width;
+ self.offset = *offset;
+ *offset = next;
+ }
+ }
+}
+
+impl Column {
+ fn new(offset: usize, width: usize) -> Self {
+ Self { offset, width }
+ }
+}
diff --git a/vendor/windows-metadata/src/file/view.rs b/vendor/windows-metadata/src/file/view.rs
new file mode 100644
index 000000000..31eb1541b
--- /dev/null
+++ b/vendor/windows-metadata/src/file/view.rs
@@ -0,0 +1,55 @@
+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/reader/filter.rs b/vendor/windows-metadata/src/filter.rs
index 4b6651fb6..c13afda44 100644
--- a/vendor/windows-metadata/src/reader/filter.rs
+++ b/vendor/windows-metadata/src/filter.rs
@@ -49,11 +49,7 @@ impl<'a> Filter<'a> {
false
}
- pub fn includes_type(&self, reader: &Reader, ty: TypeDef) -> bool {
- self.includes_type_name(reader.type_def_type_name(ty))
- }
-
- fn includes_type_name(&self, type_name: TypeName) -> bool {
+ pub fn includes_type_name(&self, type_name: TypeName) -> bool {
if self.is_empty() {
return true;
}
@@ -67,6 +63,10 @@ impl<'a> Filter<'a> {
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()
}
@@ -85,7 +85,7 @@ fn match_type_name(rule: &str, namespace: &str, name: &str) -> bool {
return false;
}
- name.starts_with(&rule[namespace.len() + 1..])
+ name == &rule[namespace.len() + 1..]
}
#[cfg(test)]
diff --git a/vendor/windows-metadata/src/reader/guid.rs b/vendor/windows-metadata/src/guid.rs
index 96444b8b2..a253530ba 100644
--- a/vendor/windows-metadata/src/reader/guid.rs
+++ b/vendor/windows-metadata/src/guid.rs
@@ -10,19 +10,19 @@ impl GUID {
fn unwrap_u32(value: &Value) -> u32 {
match value {
Value::U32(value) => *value,
- _ => unimplemented!(),
+ rest => unimplemented!("{rest:?}"),
}
}
fn unwrap_u16(value: &Value) -> u16 {
match value {
Value::U16(value) => *value,
- _ => unimplemented!(),
+ rest => unimplemented!("{rest:?}"),
}
}
fn unwrap_u8(value: &Value) -> u8 {
match value {
Value::U8(value) => *value,
- _ => unimplemented!(),
+ 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))
diff --git a/vendor/windows-metadata/src/bindings.rs b/vendor/windows-metadata/src/imp/bindings.rs
index 9e25db928..abaebdd02 100644
--- a/vendor/windows-metadata/src/bindings.rs
+++ b/vendor/windows-metadata/src/imp/bindings.rs
@@ -1,28 +1,83 @@
-// Note: these definitions are taken from `windows-sys` to avoid a circular dependency.
-#![allow(non_snake_case, non_camel_case_types)]
+// Bindings generated by `windows-bindgen` 0.51.1
-pub type IMAGE_DIRECTORY_ENTRY = u32;
-pub type IMAGE_DLL_CHARACTERISTICS = u16;
-pub type IMAGE_FILE_CHARACTERISTICS = u16;
-pub type IMAGE_FILE_MACHINE = u16;
-pub type IMAGE_OPTIONAL_HEADER_MAGIC = u16;
-pub type IMAGE_SECTION_CHARACTERISTICS = u32;
-pub type IMAGE_SUBSYSTEM = u16;
-
-pub const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: IMAGE_DIRECTORY_ENTRY = 14u32;
+#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
+pub type CorElementType = u8;
+pub const ELEMENT_TYPE_ARRAY: CorElementType = 20u8;
+pub const ELEMENT_TYPE_BOOLEAN: CorElementType = 2u8;
+pub const ELEMENT_TYPE_BYREF: CorElementType = 16u8;
+pub const ELEMENT_TYPE_CHAR: CorElementType = 3u8;
+pub const ELEMENT_TYPE_CLASS: CorElementType = 18u8;
+pub const ELEMENT_TYPE_CMOD_OPT: CorElementType = 32u8;
+pub const ELEMENT_TYPE_CMOD_REQD: CorElementType = 31u8;
+pub const ELEMENT_TYPE_GENERICINST: CorElementType = 21u8;
+pub const ELEMENT_TYPE_I: CorElementType = 24u8;
+pub const ELEMENT_TYPE_I1: CorElementType = 4u8;
+pub const ELEMENT_TYPE_I2: CorElementType = 6u8;
+pub const ELEMENT_TYPE_I4: CorElementType = 8u8;
+pub const ELEMENT_TYPE_I8: CorElementType = 10u8;
+pub const ELEMENT_TYPE_OBJECT: CorElementType = 28u8;
+pub const ELEMENT_TYPE_PTR: CorElementType = 15u8;
+pub const ELEMENT_TYPE_R4: CorElementType = 12u8;
+pub const ELEMENT_TYPE_R8: CorElementType = 13u8;
+pub const ELEMENT_TYPE_STRING: CorElementType = 14u8;
+pub const ELEMENT_TYPE_SZARRAY: CorElementType = 29u8;
+pub const ELEMENT_TYPE_U: CorElementType = 25u8;
+pub const ELEMENT_TYPE_U1: CorElementType = 5u8;
+pub const ELEMENT_TYPE_U2: CorElementType = 7u8;
+pub const ELEMENT_TYPE_U4: CorElementType = 9u8;
+pub const ELEMENT_TYPE_U8: CorElementType = 11u8;
+pub const ELEMENT_TYPE_VALUETYPE: CorElementType = 17u8;
+pub const ELEMENT_TYPE_VAR: CorElementType = 19u8;
+pub const ELEMENT_TYPE_VOID: CorElementType = 1u8;
+#[repr(C)]
+pub struct IMAGE_COR20_HEADER {
+ pub cb: u32,
+ pub MajorRuntimeVersion: u16,
+ pub MinorRuntimeVersion: u16,
+ pub MetaData: IMAGE_DATA_DIRECTORY,
+ pub Flags: u32,
+ pub Anonymous: IMAGE_COR20_HEADER_0,
+ pub Resources: IMAGE_DATA_DIRECTORY,
+ pub StrongNameSignature: IMAGE_DATA_DIRECTORY,
+ pub CodeManagerTable: IMAGE_DATA_DIRECTORY,
+ pub VTableFixups: IMAGE_DATA_DIRECTORY,
+ pub ExportAddressTableJumps: IMAGE_DATA_DIRECTORY,
+ pub ManagedNativeHeader: IMAGE_DATA_DIRECTORY,
+}
+impl ::core::marker::Copy for IMAGE_COR20_HEADER {}
+impl ::core::clone::Clone for IMAGE_COR20_HEADER {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[repr(C)]
+pub union IMAGE_COR20_HEADER_0 {
+ pub EntryPointToken: u32,
+ pub EntryPointRVA: u32,
+}
+impl ::core::marker::Copy for IMAGE_COR20_HEADER_0 {}
+impl ::core::clone::Clone for IMAGE_COR20_HEADER_0 {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[repr(C)]
+pub struct IMAGE_DATA_DIRECTORY {
+ pub VirtualAddress: u32,
+ pub Size: u32,
+}
+impl ::core::marker::Copy for IMAGE_DATA_DIRECTORY {}
+impl ::core::clone::Clone for IMAGE_DATA_DIRECTORY {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+pub type IMAGE_DIRECTORY_ENTRY = u16;
+pub const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: IMAGE_DIRECTORY_ENTRY = 14u16;
pub const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE: IMAGE_DLL_CHARACTERISTICS = 64u16;
pub const IMAGE_DLLCHARACTERISTICS_NO_SEH: IMAGE_DLL_CHARACTERISTICS = 1024u16;
pub const IMAGE_DLLCHARACTERISTICS_NX_COMPAT: IMAGE_DLL_CHARACTERISTICS = 256u16;
-pub const IMAGE_DOS_SIGNATURE: u16 = 23117u16;
-pub const IMAGE_FILE_32BIT_MACHINE: IMAGE_FILE_CHARACTERISTICS = 256u16;
-pub const IMAGE_FILE_DLL: IMAGE_FILE_CHARACTERISTICS = 8192u16;
-pub const IMAGE_FILE_EXECUTABLE_IMAGE: IMAGE_FILE_CHARACTERISTICS = 2u16;
-pub const IMAGE_FILE_MACHINE_I386: IMAGE_FILE_MACHINE = 332u16;
-pub const IMAGE_NT_OPTIONAL_HDR32_MAGIC: IMAGE_OPTIONAL_HEADER_MAGIC = 267u16;
-pub const IMAGE_NT_OPTIONAL_HDR64_MAGIC: IMAGE_OPTIONAL_HEADER_MAGIC = 523u16;
-pub const IMAGE_NT_SIGNATURE: u32 = 17744u32;
-pub const IMAGE_SUBSYSTEM_WINDOWS_CUI: IMAGE_SUBSYSTEM = 3u16;
-
+pub type IMAGE_DLL_CHARACTERISTICS = u16;
#[repr(C, packed(2))]
pub struct IMAGE_DOS_HEADER {
pub e_magic: u16,
@@ -45,7 +100,17 @@ pub struct IMAGE_DOS_HEADER {
pub e_res2: [u16; 10],
pub e_lfanew: i32,
}
-
+impl ::core::marker::Copy for IMAGE_DOS_HEADER {}
+impl ::core::clone::Clone for IMAGE_DOS_HEADER {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+pub const IMAGE_DOS_SIGNATURE: u16 = 23117u16;
+pub const IMAGE_FILE_32BIT_MACHINE: IMAGE_FILE_CHARACTERISTICS = 256u16;
+pub type IMAGE_FILE_CHARACTERISTICS = u16;
+pub const IMAGE_FILE_DLL: IMAGE_FILE_CHARACTERISTICS = 8192u16;
+pub const IMAGE_FILE_EXECUTABLE_IMAGE: IMAGE_FILE_CHARACTERISTICS = 2u16;
#[repr(C)]
pub struct IMAGE_FILE_HEADER {
pub Machine: IMAGE_FILE_MACHINE,
@@ -56,7 +121,17 @@ pub struct IMAGE_FILE_HEADER {
pub SizeOfOptionalHeader: u16,
pub Characteristics: IMAGE_FILE_CHARACTERISTICS,
}
-
+impl ::core::marker::Copy for IMAGE_FILE_HEADER {}
+impl ::core::clone::Clone for IMAGE_FILE_HEADER {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+pub type IMAGE_FILE_MACHINE = u16;
+pub const IMAGE_FILE_MACHINE_I386: IMAGE_FILE_MACHINE = 332u16;
+pub const IMAGE_NT_OPTIONAL_HDR32_MAGIC: IMAGE_OPTIONAL_HEADER_MAGIC = 267u16;
+pub const IMAGE_NT_OPTIONAL_HDR64_MAGIC: IMAGE_OPTIONAL_HEADER_MAGIC = 523u16;
+pub const IMAGE_NT_SIGNATURE: u32 = 17744u32;
#[repr(C)]
pub struct IMAGE_OPTIONAL_HEADER32 {
pub Magic: IMAGE_OPTIONAL_HEADER_MAGIC,
@@ -91,7 +166,12 @@ pub struct IMAGE_OPTIONAL_HEADER32 {
pub NumberOfRvaAndSizes: u32,
pub DataDirectory: [IMAGE_DATA_DIRECTORY; 16],
}
-
+impl ::core::marker::Copy for IMAGE_OPTIONAL_HEADER32 {}
+impl ::core::clone::Clone for IMAGE_OPTIONAL_HEADER32 {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
#[repr(C, packed(4))]
pub struct IMAGE_OPTIONAL_HEADER64 {
pub Magic: IMAGE_OPTIONAL_HEADER_MAGIC,
@@ -125,7 +205,14 @@ pub struct IMAGE_OPTIONAL_HEADER64 {
pub NumberOfRvaAndSizes: u32,
pub DataDirectory: [IMAGE_DATA_DIRECTORY; 16],
}
-
+impl ::core::marker::Copy for IMAGE_OPTIONAL_HEADER64 {}
+impl ::core::clone::Clone for IMAGE_OPTIONAL_HEADER64 {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+pub type IMAGE_OPTIONAL_HEADER_MAGIC = u16;
+pub type IMAGE_SECTION_CHARACTERISTICS = u32;
#[repr(C)]
pub struct IMAGE_SECTION_HEADER {
pub Name: [u8; 8],
@@ -139,37 +226,22 @@ pub struct IMAGE_SECTION_HEADER {
pub NumberOfLinenumbers: u16,
pub Characteristics: IMAGE_SECTION_CHARACTERISTICS,
}
-
+impl ::core::marker::Copy for IMAGE_SECTION_HEADER {}
+impl ::core::clone::Clone for IMAGE_SECTION_HEADER {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
#[repr(C)]
pub union IMAGE_SECTION_HEADER_0 {
pub PhysicalAddress: u32,
pub VirtualSize: u32,
}
-
-#[repr(C)]
-pub struct IMAGE_DATA_DIRECTORY {
- pub VirtualAddress: u32,
- pub Size: u32,
-}
-
-#[repr(C)]
-pub struct IMAGE_COR20_HEADER {
- pub cb: u32,
- pub MajorRuntimeVersion: u16,
- pub MinorRuntimeVersion: u16,
- pub MetaData: IMAGE_DATA_DIRECTORY,
- pub Flags: u32,
- pub Anonymous: IMAGE_COR20_HEADER_0,
- pub Resources: IMAGE_DATA_DIRECTORY,
- pub StrongNameSignature: IMAGE_DATA_DIRECTORY,
- pub CodeManagerTable: IMAGE_DATA_DIRECTORY,
- pub VTableFixups: IMAGE_DATA_DIRECTORY,
- pub ExportAddressTableJumps: IMAGE_DATA_DIRECTORY,
- pub ManagedNativeHeader: IMAGE_DATA_DIRECTORY,
-}
-
-#[repr(C)]
-pub union IMAGE_COR20_HEADER_0 {
- pub EntryPointToken: u32,
- pub EntryPointRVA: u32,
+impl ::core::marker::Copy for IMAGE_SECTION_HEADER_0 {}
+impl ::core::clone::Clone for IMAGE_SECTION_HEADER_0 {
+ fn clone(&self) -> Self {
+ *self
+ }
}
+pub type IMAGE_SUBSYSTEM = u16;
+pub const IMAGE_SUBSYSTEM_WINDOWS_CUI: IMAGE_SUBSYSTEM = 3u16;
diff --git a/vendor/windows-metadata/src/imp.rs b/vendor/windows-metadata/src/imp/mod.rs
index 27a735a45..571d0f063 100644
--- a/vendor/windows-metadata/src/imp.rs
+++ b/vendor/windows-metadata/src/imp/mod.rs
@@ -1,3 +1,6 @@
+mod bindings;
+pub use bindings::*;
+
#[repr(C)]
#[derive(Default)]
pub struct METADATA_HEADER {
diff --git a/vendor/windows-metadata/src/lib.rs b/vendor/windows-metadata/src/lib.rs
index 0e832603c..70a85c5b1 100644
--- a/vendor/windows-metadata/src/lib.rs
+++ b/vendor/windows-metadata/src/lib.rs
@@ -1,57 +1,463 @@
-#![allow(dead_code)]
+#[doc(hidden)]
+pub mod imp;
-use std::collections::*;
mod attributes;
-mod bindings;
-mod imp;
-pub mod reader;
-pub mod writer;
+mod blob;
+mod codes;
+mod file;
+mod filter;
+mod guid;
+mod row;
+mod r#type;
+mod type_name;
pub use attributes::*;
-use bindings::*;
+pub use blob::Blob;
+pub use codes::*;
+pub use file::*;
+pub use filter::Filter;
+pub use guid::GUID;
use imp::*;
-use std::io::*;
-use std::mem::*;
-use std::ptr::*;
+pub use r#type::Type;
+pub use row::*;
+use std::collections::*;
+pub use type_name::TypeName;
+
+// TODO: move to riddle
+#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
+pub enum TypeKind {
+ Interface,
+ Class,
+ Enum,
+ Struct,
+ Delegate,
+}
+
+#[derive(Debug)]
+pub enum Value {
+ Bool(bool),
+ U8(u8),
+ I8(i8),
+ U16(u16),
+ I16(i16),
+ U32(u32),
+ I32(i32),
+ U64(u64),
+ I64(i64),
+ F32(f32),
+ F64(f64),
+ String(String),
+ TypeName(String),
+ TypeRef(TypeDefOrRef),
+ EnumDef(TypeDef, Box<Self>),
+}
+
+pub struct MethodDefSig {
+ pub call_flags: MethodCallAttributes,
+ pub return_type: Type,
+ 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>>>,
-macro_rules! flags {
- ($name:ident, $size:ty) => {
- #[derive(Default, Copy, Clone, PartialEq, Eq)]
- pub struct $name(pub $size);
- impl $name {
- pub fn contains(&self, contains: Self) -> bool {
- *self & contains == contains
+ // 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);
}
}
- impl std::ops::BitOr for $name {
- type Output = Self;
- fn bitor(self, other: Self) -> Self {
- Self(self.0 | other.0)
+ 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();
}
}
- impl std::ops::BitAnd for $name {
- type Output = Self;
- fn bitand(self, other: Self) -> Self {
- Self(self.0 & other.0)
+ 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,
}
- impl std::ops::BitOrAssign for $name {
- fn bitor_assign(&mut self, other: Self) {
- self.0.bitor_assign(other.0)
+ }
+
+ 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;
}
}
- impl std::ops::BitAndAssign for $name {
- fn bitand_assign(&mut self, other: Self) {
- self.0.bitand_assign(other.0)
+
+ // TODO: remove this
+ for (from, to) in REMAP_TYPES {
+ if full_name == from {
+ full_name = to;
+ break;
}
}
- impl std::ops::Not for $name {
- type Output = Self;
- fn not(self) -> Self {
- Self(self.0.not())
+
+ 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:?}"),
+ }
+ }
}
-pub(crate) use flags;
+impl<'a> RowReader<'a> for Reader<'a> {
+ fn row_file<R: AsRow>(&self, row: R) -> &'a File {
+ &self.files[row.to_row().file]
+ }
+}
+
+fn trim_tick(name: &str) -> &str {
+ if name.as_bytes().iter().rev().nth(1) == Some(&b'`') {
+ &name[..name.len() - 2]
+ } else {
+ name
+ }
+}
+
+// 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/file.rs b/vendor/windows-metadata/src/reader/file.rs
deleted file mode 100644
index b00b4fc52..000000000
--- a/vendor/windows-metadata/src/reader/file.rs
+++ /dev/null
@@ -1,537 +0,0 @@
-use super::*;
-use std::cmp::*;
-
-#[derive(Default)]
-pub struct File {
- bytes: Vec<u8>,
- strings: usize,
- blobs: usize,
- pub(crate) tables: [Table; TABLE_LEN],
-}
-
-#[derive(Default)]
-pub struct Table {
- pub offset: usize,
- pub len: usize,
- pub width: usize,
- pub columns: [Column; 6],
-}
-
-#[derive(Default)]
-pub struct Column {
- pub offset: usize,
- pub width: usize,
-}
-
-pub const TABLE_CONSTANT: usize = 0;
-pub const TABLE_CUSTOMATTRIBUTE: usize = 1;
-pub const TABLE_FIELD: usize = 2;
-pub const TABLE_GENERICPARAM: usize = 3;
-pub const TABLE_INTERFACEIMPL: usize = 4;
-pub const TABLE_MEMBERREF: usize = 5;
-pub const TABLE_METHODDEF: usize = 6;
-pub const TABLE_PARAM: usize = 7;
-pub const TABLE_TYPEDEF: usize = 8;
-pub const TABLE_TYPEREF: usize = 9;
-pub const TABLE_TYPESPEC: usize = 10;
-pub const TABLE_IMPLMAP: usize = 11;
-pub const TABLE_MODULEREF: usize = 12;
-pub const TABLE_NESTEDCLASS: usize = 13;
-pub const TABLE_MODULE: usize = 14;
-pub const TABLE_ASSEMBLYREF: usize = 15;
-pub const TABLE_CLASSLAYOUT: usize = 16;
-pub const TABLE_LEN: usize = 17;
-
-fn error(message: &str) -> Error {
- Error::new(ErrorKind::Other, message)
-}
-
-fn error_invalid_winmd() -> Error {
- error("File is not a valid `winmd` file")
-}
-
-impl File {
- pub fn with_default(paths: &[&str]) -> Result<Vec<Self>> {
- let mut files = vec![Self::from_buffer(std::include_bytes!("../../default/Windows.winmd").to_vec())?, Self::from_buffer(std::include_bytes!("../../default/Windows.Wdk.winmd").to_vec())?, Self::from_buffer(std::include_bytes!("../../default/Windows.Win32.winmd").to_vec())?];
-
- for path in paths {
- files.push(Self::new(std::path::Path::new(path))?);
- }
-
- Ok(files)
- }
-
- pub fn new<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
- Self::from_buffer(std::fs::read(&path)?)
- }
-
- pub fn from_buffer(bytes: Vec<u8>) -> Result<Self> {
- let mut result = File { bytes, ..Default::default() };
-
- let dos = result.bytes.view_as::<IMAGE_DOS_HEADER>(0);
-
- if dos.e_magic != IMAGE_DOS_SIGNATURE as _ || result.bytes.copy_as::<u32>(dos.e_lfanew as _) != IMAGE_NT_SIGNATURE {
- return Err(error_invalid_winmd());
- }
-
- let file_offset = dos.e_lfanew as usize + size_of::<u32>();
- let file = result.bytes.view_as::<IMAGE_FILE_HEADER>(file_offset);
-
- let optional_offset = file_offset + size_of::<IMAGE_FILE_HEADER>();
-
- let (com_virtual_address, sections) = match result.bytes.copy_as::<u16>(optional_offset) {
- IMAGE_NT_OPTIONAL_HDR32_MAGIC => {
- let optional = result.bytes.view_as::<IMAGE_OPTIONAL_HEADER32>(optional_offset);
- (optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(optional_offset + size_of::<IMAGE_OPTIONAL_HEADER32>(), file.NumberOfSections as usize))
- }
- IMAGE_NT_OPTIONAL_HDR64_MAGIC => {
- let optional = result.bytes.view_as::<IMAGE_OPTIONAL_HEADER64>(optional_offset);
- (optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize].VirtualAddress, result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(optional_offset + size_of::<IMAGE_OPTIONAL_HEADER64>(), file.NumberOfSections as usize))
- }
- _ => return Err(error_invalid_winmd()),
- };
-
- let clr = result.bytes.view_as::<IMAGE_COR20_HEADER>(offset_from_rva(section_from_rva(sections, com_virtual_address)?, com_virtual_address) as _);
-
- if clr.cb != size_of::<IMAGE_COR20_HEADER>() as _ {
- return Err(error_invalid_winmd());
- }
-
- let metadata_offset = offset_from_rva(section_from_rva(sections, clr.MetaData.VirtualAddress)?, clr.MetaData.VirtualAddress);
- let metadata = result.bytes.view_as::<METADATA_HEADER>(metadata_offset as _);
-
- if metadata.signature != METADATA_SIGNATURE {
- return Err(error_invalid_winmd());
- }
-
- // The METADATA_HEADER struct is not a fixed size so have to offset a little more carefully.
- let mut view = metadata_offset + metadata.length as usize + 20;
- let mut tables_data: (usize, usize) = (0, 0);
-
- for _ in 0..result.bytes.copy_as::<u16>(metadata_offset + metadata.length as usize + 18) {
- let stream_offset = result.bytes.copy_as::<u32>(view) as usize;
- let stream_len = result.bytes.copy_as::<u32>(view + 4) as usize;
- let stream_name = result.bytes.view_as_str(view + 8);
- match stream_name {
- b"#Strings" => result.strings = metadata_offset + stream_offset,
- b"#Blob" => result.blobs = metadata_offset + stream_offset,
- b"#~" => tables_data = (metadata_offset + stream_offset, stream_len),
- b"#GUID" => {}
- b"#US" => {}
- _ => unimplemented!(),
- }
- let mut padding = 4 - stream_name.len() % 4;
- if padding == 0 {
- padding = 4;
- }
- view += 8 + stream_name.len() + padding;
- }
-
- let heap_sizes = result.bytes.copy_as::<u8>(tables_data.0 + 6);
- let string_index_size = if (heap_sizes & 1) == 1 { 4 } else { 2 };
- let guid_index_size = if (heap_sizes >> 1 & 1) == 1 { 4 } else { 2 };
- let blob_index_size = if (heap_sizes >> 2 & 1) == 1 { 4 } else { 2 };
- let valid_bits = result.bytes.copy_as::<u64>(tables_data.0 + 8);
- view = tables_data.0 + 24;
-
- // These tables are unused by the reader, but needed temporarily to calculate sizes and offsets for subsequent tables.
- let unused_empty = Table::default();
- let mut unused_assembly = Table::default();
- let mut unused_assembly_os = Table::default();
- let mut unused_assembly_processor = Table::default();
- let mut unused_assembly_ref_os = Table::default();
- let mut unused_assembly_ref_processor = Table::default();
- let mut unused_decl_security = Table::default();
- let mut unused_event = Table::default();
- let mut unused_event_map = Table::default();
- let mut unused_exported_type = Table::default();
- let mut unused_field_layout = Table::default();
- let mut unused_field_marshal = Table::default();
- let mut unused_field_rva = Table::default();
- let mut unused_file = Table::default();
- let mut unused_generic_param_constraint = Table::default();
- let mut unused_manifest_resource = Table::default();
- let mut unused_method_impl = Table::default();
- let mut unused_method_semantics = Table::default();
- let mut unused_method_spec = Table::default();
- let mut unused_property = Table::default();
- let mut unused_property_map = Table::default();
- let mut unused_standalone_sig = Table::default();
-
- for i in 0..64 {
- if (valid_bits >> i & 1) == 0 {
- continue;
- }
-
- let len = result.bytes.copy_as::<u32>(view) as _;
- view += 4;
-
- match i {
- 0x00 => result.tables[TABLE_MODULE].len = len,
- 0x01 => result.tables[TABLE_TYPEREF].len = len,
- 0x02 => result.tables[TABLE_TYPEDEF].len = len,
- 0x04 => result.tables[TABLE_FIELD].len = len,
- 0x06 => result.tables[TABLE_METHODDEF].len = len,
- 0x08 => result.tables[TABLE_PARAM].len = len,
- 0x09 => result.tables[TABLE_INTERFACEIMPL].len = len,
- 0x0a => result.tables[TABLE_MEMBERREF].len = len,
- 0x0b => result.tables[TABLE_CONSTANT].len = len,
- 0x0c => result.tables[TABLE_CUSTOMATTRIBUTE].len = len,
- 0x0d => unused_field_marshal.len = len,
- 0x0e => unused_decl_security.len = len,
- 0x0f => result.tables[TABLE_CLASSLAYOUT].len = len,
- 0x10 => unused_field_layout.len = len,
- 0x11 => unused_standalone_sig.len = len,
- 0x12 => unused_event_map.len = len,
- 0x14 => unused_event.len = len,
- 0x15 => unused_property_map.len = len,
- 0x17 => unused_property.len = len,
- 0x18 => unused_method_semantics.len = len,
- 0x19 => unused_method_impl.len = len,
- 0x1a => result.tables[TABLE_MODULEREF].len = len,
- 0x1b => result.tables[TABLE_TYPESPEC].len = len,
- 0x1c => result.tables[TABLE_IMPLMAP].len = len,
- 0x1d => unused_field_rva.len = len,
- 0x20 => unused_assembly.len = len,
- 0x21 => unused_assembly_processor.len = len,
- 0x22 => unused_assembly_os.len = len,
- 0x23 => result.tables[TABLE_ASSEMBLYREF].len = len,
- 0x24 => unused_assembly_ref_processor.len = len,
- 0x25 => unused_assembly_ref_os.len = len,
- 0x26 => unused_file.len = len,
- 0x27 => unused_exported_type.len = len,
- 0x28 => unused_manifest_resource.len = len,
- 0x29 => result.tables[TABLE_NESTEDCLASS].len = len,
- 0x2a => result.tables[TABLE_GENERICPARAM].len = len,
- 0x2b => unused_method_spec.len = len,
- 0x2c => unused_generic_param_constraint.len = len,
- _ => unreachable!(),
- };
- }
-
- let tables = &result.tables;
- let type_def_or_ref = coded_index_size(&[tables[TABLE_TYPEDEF].len, tables[TABLE_TYPEREF].len, tables[TABLE_TYPESPEC].len]);
- let has_constant = coded_index_size(&[tables[TABLE_FIELD].len, tables[TABLE_PARAM].len, unused_property.len]);
- let has_field_marshal = coded_index_size(&[tables[TABLE_FIELD].len, tables[TABLE_PARAM].len]);
- let has_decl_security = coded_index_size(&[tables[TABLE_TYPEDEF].len, tables[TABLE_METHODDEF].len, unused_assembly.len]);
- let member_ref_parent = coded_index_size(&[tables[TABLE_TYPEDEF].len, tables[TABLE_TYPEREF].len, tables[TABLE_MODULEREF].len, tables[TABLE_METHODDEF].len, tables[TABLE_TYPESPEC].len]);
- let has_semantics = coded_index_size(&[unused_event.len, unused_property.len]);
- let method_def_or_ref = coded_index_size(&[tables[TABLE_METHODDEF].len, tables[TABLE_MEMBERREF].len]);
- let member_forwarded = coded_index_size(&[tables[TABLE_FIELD].len, tables[TABLE_METHODDEF].len]);
- let implementation = coded_index_size(&[unused_file.len, tables[TABLE_ASSEMBLYREF].len, unused_exported_type.len]);
- let custom_attribute_type = coded_index_size(&[tables[TABLE_METHODDEF].len, tables[TABLE_MEMBERREF].len, unused_empty.len, unused_empty.len, unused_empty.len]);
- let resolution_scope = coded_index_size(&[tables[TABLE_MODULE].len, tables[TABLE_MODULEREF].len, tables[TABLE_ASSEMBLYREF].len, tables[TABLE_TYPEREF].len]);
- let type_or_method_def = coded_index_size(&[tables[TABLE_TYPEDEF].len, tables[TABLE_METHODDEF].len]);
-
- let has_custom_attribute = coded_index_size(&[
- tables[TABLE_METHODDEF].len,
- tables[TABLE_FIELD].len,
- tables[TABLE_TYPEREF].len,
- tables[TABLE_TYPEDEF].len,
- tables[TABLE_PARAM].len,
- tables[TABLE_INTERFACEIMPL].len,
- tables[TABLE_MEMBERREF].len,
- tables[TABLE_MODULE].len,
- unused_property.len,
- unused_event.len,
- unused_standalone_sig.len,
- tables[TABLE_MODULEREF].len,
- tables[TABLE_TYPESPEC].len,
- unused_assembly.len,
- tables[TABLE_ASSEMBLYREF].len,
- unused_file.len,
- unused_exported_type.len,
- unused_manifest_resource.len,
- tables[TABLE_GENERICPARAM].len,
- unused_generic_param_constraint.len,
- unused_method_spec.len,
- ]);
-
- unused_assembly.set_columns(4, 8, 4, blob_index_size, string_index_size, string_index_size);
- unused_assembly_os.set_columns(4, 4, 4, 0, 0, 0);
- unused_assembly_processor.set_columns(4, 0, 0, 0, 0, 0);
- result.tables[TABLE_ASSEMBLYREF].set_columns(8, 4, blob_index_size, string_index_size, string_index_size, blob_index_size);
- unused_assembly_ref_os.set_columns(4, 4, 4, result.tables[TABLE_ASSEMBLYREF].index_width(), 0, 0);
- unused_assembly_ref_processor.set_columns(4, result.tables[TABLE_ASSEMBLYREF].index_width(), 0, 0, 0, 0);
- result.tables[TABLE_CLASSLAYOUT].set_columns(2, 4, result.tables[TABLE_TYPEDEF].index_width(), 0, 0, 0);
- result.tables[TABLE_CONSTANT].set_columns(2, has_constant, blob_index_size, 0, 0, 0);
- result.tables[TABLE_CUSTOMATTRIBUTE].set_columns(has_custom_attribute, custom_attribute_type, blob_index_size, 0, 0, 0);
- unused_decl_security.set_columns(2, has_decl_security, blob_index_size, 0, 0, 0);
- unused_event_map.set_columns(result.tables[TABLE_TYPEDEF].index_width(), unused_event.index_width(), 0, 0, 0, 0);
- unused_event.set_columns(2, string_index_size, type_def_or_ref, 0, 0, 0);
- unused_exported_type.set_columns(4, 4, string_index_size, string_index_size, implementation, 0);
- result.tables[TABLE_FIELD].set_columns(2, string_index_size, blob_index_size, 0, 0, 0);
- unused_field_layout.set_columns(4, result.tables[TABLE_FIELD].index_width(), 0, 0, 0, 0);
- unused_field_marshal.set_columns(has_field_marshal, blob_index_size, 0, 0, 0, 0);
- unused_field_rva.set_columns(4, result.tables[TABLE_FIELD].index_width(), 0, 0, 0, 0);
- unused_file.set_columns(4, string_index_size, blob_index_size, 0, 0, 0);
- result.tables[TABLE_GENERICPARAM].set_columns(2, 2, type_or_method_def, string_index_size, 0, 0);
- unused_generic_param_constraint.set_columns(result.tables[TABLE_GENERICPARAM].index_width(), type_def_or_ref, 0, 0, 0, 0);
- result.tables[TABLE_IMPLMAP].set_columns(2, member_forwarded, string_index_size, result.tables[TABLE_MODULEREF].index_width(), 0, 0);
- result.tables[TABLE_INTERFACEIMPL].set_columns(result.tables[TABLE_TYPEDEF].index_width(), type_def_or_ref, 0, 0, 0, 0);
- unused_manifest_resource.set_columns(4, 4, string_index_size, implementation, 0, 0);
- result.tables[TABLE_MEMBERREF].set_columns(member_ref_parent, string_index_size, blob_index_size, 0, 0, 0);
- result.tables[TABLE_METHODDEF].set_columns(4, 2, 2, string_index_size, blob_index_size, result.tables[TABLE_PARAM].index_width());
- unused_method_impl.set_columns(result.tables[TABLE_TYPEDEF].index_width(), method_def_or_ref, method_def_or_ref, 0, 0, 0);
- unused_method_semantics.set_columns(2, result.tables[TABLE_METHODDEF].index_width(), has_semantics, 0, 0, 0);
- unused_method_spec.set_columns(method_def_or_ref, blob_index_size, 0, 0, 0, 0);
- result.tables[TABLE_MODULE].set_columns(2, string_index_size, guid_index_size, guid_index_size, guid_index_size, 0);
- result.tables[TABLE_MODULEREF].set_columns(string_index_size, 0, 0, 0, 0, 0);
- result.tables[TABLE_NESTEDCLASS].set_columns(result.tables[TABLE_TYPEDEF].index_width(), result.tables[TABLE_TYPEDEF].index_width(), 0, 0, 0, 0);
- result.tables[TABLE_PARAM].set_columns(2, 2, string_index_size, 0, 0, 0);
- unused_property.set_columns(2, string_index_size, blob_index_size, 0, 0, 0);
- unused_property_map.set_columns(result.tables[TABLE_TYPEDEF].index_width(), unused_property.index_width(), 0, 0, 0, 0);
- unused_standalone_sig.set_columns(blob_index_size, 0, 0, 0, 0, 0);
- result.tables[TABLE_TYPEDEF].set_columns(4, string_index_size, string_index_size, type_def_or_ref, result.tables[TABLE_FIELD].index_width(), result.tables[TABLE_METHODDEF].index_width());
- result.tables[TABLE_TYPEREF].set_columns(resolution_scope, string_index_size, string_index_size, 0, 0, 0);
- result.tables[TABLE_TYPESPEC].set_columns(blob_index_size, 0, 0, 0, 0, 0);
-
- result.tables[TABLE_MODULE].set_data(&mut view);
- result.tables[TABLE_TYPEREF].set_data(&mut view);
- result.tables[TABLE_TYPEDEF].set_data(&mut view);
- result.tables[TABLE_FIELD].set_data(&mut view);
- result.tables[TABLE_METHODDEF].set_data(&mut view);
- result.tables[TABLE_PARAM].set_data(&mut view);
- result.tables[TABLE_INTERFACEIMPL].set_data(&mut view);
- result.tables[TABLE_MEMBERREF].set_data(&mut view);
- result.tables[TABLE_CONSTANT].set_data(&mut view);
- result.tables[TABLE_CUSTOMATTRIBUTE].set_data(&mut view);
- unused_field_marshal.set_data(&mut view);
- unused_decl_security.set_data(&mut view);
- result.tables[TABLE_CLASSLAYOUT].set_data(&mut view);
- unused_field_layout.set_data(&mut view);
- unused_standalone_sig.set_data(&mut view);
- unused_event_map.set_data(&mut view);
- unused_event.set_data(&mut view);
- unused_property_map.set_data(&mut view);
- unused_property.set_data(&mut view);
- unused_method_semantics.set_data(&mut view);
- unused_method_impl.set_data(&mut view);
- result.tables[TABLE_MODULEREF].set_data(&mut view);
- result.tables[TABLE_TYPESPEC].set_data(&mut view);
- result.tables[TABLE_IMPLMAP].set_data(&mut view);
- unused_field_rva.set_data(&mut view);
- unused_assembly.set_data(&mut view);
- unused_assembly_processor.set_data(&mut view);
- unused_assembly_os.set_data(&mut view);
- result.tables[TABLE_ASSEMBLYREF].set_data(&mut view);
- unused_assembly_ref_processor.set_data(&mut view);
- unused_assembly_ref_os.set_data(&mut view);
- unused_file.set_data(&mut view);
- unused_exported_type.set_data(&mut view);
- unused_manifest_resource.set_data(&mut view);
- result.tables[TABLE_NESTEDCLASS].set_data(&mut view);
- result.tables[TABLE_GENERICPARAM].set_data(&mut view);
-
- Ok(result)
- }
-
- 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;
- match column.width {
- 1 => self.bytes.copy_as::<u8>(offset) as _,
- 2 => self.bytes.copy_as::<u16>(offset) as _,
- 4 => self.bytes.copy_as::<u32>(offset) as _,
- _ => self.bytes.copy_as::<u64>(offset) as _,
- }
- }
-
- /// Returns the string from the `#Strings` stream as referenced by
- /// the (table, row, column) triple.
- ///
- /// # Panics
- ///
- /// * When any element of the (table, row, column) triple is invalid.
- /// * When the offset in the string table is out of bounds.
- /// * When no null terminator can be found in the string table.
- /// * When the null-terminated string is not valid utf-8.
- pub fn str(&self, row: usize, table: usize, column: usize) -> &str {
- let offset = self.strings + self.usize(row, table, column);
-
- let bytes = &self.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")
- }
-
- pub fn blob(&self, row: usize, table: usize, column: usize) -> &[u8] {
- let offset = self.blobs + self.usize(row, table, column);
- let initial_byte = self.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),
- _ => unimplemented!(),
- };
- let mut blob_size = blob_size as usize;
- for byte in &self.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;
- &self.bytes[offset..offset + blob_size]
- }
-
- pub fn equal_range(&self, table: usize, column: usize, value: usize) -> (usize, usize) {
- let mut first = 0;
- let mut last = self.tables[table].len;
- let mut count = last;
- loop {
- if count == 0 {
- last = first;
- break;
- }
- let count2 = count / 2;
- let middle = first + count2;
- let middle_value = self.usize(middle, table, column);
- match middle_value.cmp(&value) {
- Ordering::Less => {
- first = middle + 1;
- count -= count2 + 1;
- }
- Ordering::Greater => count = count2,
- Ordering::Equal => {
- let first2 = self.lower_bound_of(table, first, middle, column, value);
- first += count;
- last = self.upper_bound_of(table, middle + 1, first, column, value);
- first = first2;
- break;
- }
- }
- }
- (first, last)
- }
-
- 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;
- let middle = first + count2;
- if self.usize(middle, table, column) < value {
- first = middle + 1;
- count -= count2 + 1;
- } else {
- count = count2;
- }
- }
- first
- }
-
- 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;
- let middle = first + count2;
- if value < self.usize(middle, table, column) {
- count = count2
- } else {
- first = middle + 1;
- count -= count2 + 1;
- }
- }
- first
- }
-}
-
-impl Table {
- fn index_width(&self) -> usize {
- if self.len < (1 << 16) {
- 2
- } else {
- 4
- }
- }
-
- fn set_columns(&mut self, a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) {
- self.width = a + b + c + d + e + f;
- self.columns[0] = Column::new(0, a);
- if b != 0 {
- self.columns[1] = Column::new(a, b);
- }
- if c != 0 {
- self.columns[2] = Column::new(a + b, c);
- }
- if d != 0 {
- self.columns[3] = Column::new(a + b + c, d);
- }
- if e != 0 {
- self.columns[4] = Column::new(a + b + c + d, e);
- }
- if f != 0 {
- self.columns[5] = Column::new(a + b + c + d + e, f);
- }
- }
-
- fn set_data(&mut self, offset: &mut usize) {
- if self.len != 0 {
- let next = *offset + self.len * self.width;
- self.offset = *offset;
- *offset = next;
- }
- }
-}
-
-impl Column {
- fn new(offset: usize, width: usize) -> Self {
- Self { offset, width }
- }
-}
-
-macro_rules! assert_proper_length {
- ($self:expr, $t:ty, $offset:expr, $size:expr) => {
- let enough_room = $offset + $size <= $self.len();
- assert!(enough_room, "Invalid file: not enough bytes at offset {} to represent T", $offset);
- };
-}
-
-macro_rules! assert_proper_length_and_alignment {
- ($self:expr, $t:ty, $offset:expr, $size:expr) => {{
- assert_proper_length!($self, $t, $offset, $size);
- let ptr = &$self[$offset] as *const u8 as *const $t;
- let properly_aligned = ptr.align_offset(align_of::<$t>()) == 0;
- assert!(properly_aligned, "Invalid file: offset {} is not properly aligned to T", $offset);
- ptr
- }};
-}
-
-trait View {
- fn view_as<T>(&self, offset: usize) -> &T;
- fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> &[T];
- fn copy_as<T: Copy>(&self, offset: usize) -> T;
- fn view_as_str(&self, offset: usize) -> &[u8];
-}
-
-impl View for [u8] {
- fn view_as<T>(&self, offset: usize) -> &T {
- let ptr = assert_proper_length_and_alignment!(self, T, offset, size_of::<T>());
- unsafe { &*ptr }
- }
-
- fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> &[T] {
- let ptr = assert_proper_length_and_alignment!(self, T, offset, size_of::<T>() * len);
- unsafe { std::slice::from_raw_parts(ptr, len) }
- }
-
- fn copy_as<T>(&self, offset: usize) -> T {
- assert_proper_length!(self, T, offset, size_of::<T>());
- unsafe {
- let mut data = MaybeUninit::zeroed().assume_init();
- copy_nonoverlapping(self[offset..].as_ptr(), &mut data as *mut T as *mut u8, size_of::<T>());
- data
- }
- }
-
- fn view_as_str(&self, offset: usize) -> &[u8] {
- let buffer = &self[offset..];
- let index = buffer.iter().position(|c| *c == b'\0').expect("Invalid file");
- &self[offset..offset + index]
- }
-}
-
-fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Result<&IMAGE_SECTION_HEADER> {
- sections.iter().find(|&s| rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize }).ok_or_else(error_invalid_winmd)
-}
-
-fn offset_from_rva(section: &IMAGE_SECTION_HEADER, rva: u32) -> usize {
- (rva - section.VirtualAddress + section.PointerToRawData) as usize
-}
diff --git a/vendor/windows-metadata/src/reader/mod.rs b/vendor/windows-metadata/src/reader/mod.rs
deleted file mode 100644
index 7e551cc8f..000000000
--- a/vendor/windows-metadata/src/reader/mod.rs
+++ /dev/null
@@ -1,1833 +0,0 @@
-mod blob;
-mod codes;
-mod file;
-mod filter;
-mod guid;
-mod row;
-mod tree;
-mod r#type;
-mod type_name;
-
-pub use super::*;
-pub use blob::*;
-pub use codes::*;
-pub use file::*;
-pub use filter::*;
-pub use guid::*;
-pub use r#type::*;
-pub use row::*;
-pub use tree::*;
-pub use type_name::*;
-
-macro_rules! tables {
- ($($name:ident,)*) => ($(
- #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
- pub struct $name(pub Row);
- )*)
-}
-
-tables! {
- Attribute,
- ClassLayout,
- Constant,
- Field,
- GenericParam,
- ImplMap,
- InterfaceImpl,
- MemberRef,
- MethodDef,
- ModuleRef,
- Param,
- TypeDef,
- TypeRef,
- TypeSpec,
-}
-
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub struct Interface {
- pub ty: Type,
- pub kind: InterfaceKind,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
-pub enum InterfaceKind {
- None,
- Default,
- Overridable,
- Static,
- Base,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub struct QueryPosition {
- pub object: usize,
- pub guid: usize,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub enum SignatureKind {
- Query(QueryPosition),
- QueryOptional(QueryPosition),
- ResultValue,
- ResultVoid,
- ReturnStruct,
- ReturnValue,
- ReturnVoid,
- PreserveSig,
-}
-
-#[derive(Copy, Clone, Eq, PartialEq)]
-pub enum SignatureParamKind {
- ArrayFixed(usize),
- ArrayRelativeLen(usize),
- ArrayRelativeByteLen(usize),
- ArrayRelativePtr(usize),
- TryInto,
- IntoParam,
- OptionalPointer,
- ValueType,
- Blittable,
- Other,
-}
-
-impl SignatureParamKind {
- fn is_array(&self) -> bool {
- matches!(self, Self::ArrayFixed(_) | Self::ArrayRelativeLen(_) | Self::ArrayRelativeByteLen(_) | Self::ArrayRelativePtr(_))
- }
-}
-
-#[derive(PartialEq, Eq)]
-pub enum AsyncKind {
- None,
- Action,
- ActionWithProgress,
- Operation,
- OperationWithProgress,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
-pub enum TypeKind {
- Interface,
- Class,
- Enum,
- Struct,
- Delegate,
-}
-
-pub enum Value {
- Bool(bool),
- U8(u8),
- I8(i8),
- U16(u16),
- I16(i16),
- U32(u32),
- I32(i32),
- U64(u64),
- I64(i64),
- F32(f32),
- F64(f64),
- String(String),
- TypeDef(TypeDef),
- Enum(TypeDef, Integer),
-}
-
-pub enum Integer {
- U8(u8),
- I8(i8),
- U16(u16),
- I16(i16),
- U32(u32),
- I32(i32),
- U64(u64),
- I64(i64),
-}
-
-pub struct Signature {
- pub def: MethodDef,
- pub params: Vec<SignatureParam>,
- pub return_type: Option<Type>,
-}
-
-pub struct SignatureParam {
- pub def: Param,
- pub ty: Type,
- pub kind: SignatureParamKind,
-}
-
-#[derive(Default, Clone)]
-pub struct Cfg<'a> {
- pub types: BTreeMap<&'a str, BTreeSet<TypeDef>>,
- pub core_types: BTreeSet<Type>,
- pub arches: BTreeSet<&'static str>,
- pub implement: bool,
-}
-
-impl<'a> Cfg<'a> {
- pub fn add_feature(&mut self, feature: &'a str) {
- self.types.entry(feature).or_default();
- }
- pub fn union(&self, other: &Self) -> Self {
- let mut union = Self::default();
- self.types.keys().for_each(|feature| {
- union.types.entry(feature).or_default();
- });
- other.types.keys().for_each(|feature| {
- union.types.entry(feature).or_default();
- });
- self.arches.iter().for_each(|arch| {
- union.arches.insert(arch);
- });
- other.arches.iter().for_each(|arch| {
- union.arches.insert(arch);
- });
- union
- }
-}
-
-pub struct Reader<'a> {
- files: &'a [File],
- types: HashMap<&'a str, BTreeMap<&'a str, Vec<TypeDef>>>,
- nested: HashMap<TypeDef, BTreeMap<&'a str, TypeDef>>,
-}
-
-impl<'a> Reader<'a> {
- pub fn new(files: &'a [File]) -> Self {
- let mut types = HashMap::<&'a str, BTreeMap<&'a str, Vec<TypeDef>>>::new();
- let mut nested = HashMap::<TypeDef, BTreeMap<&'a str, TypeDef>>::new();
- for (file_index, file) in files.iter().enumerate() {
- for row in 0..file.tables[TABLE_TYPEDEF].len {
- let key = Row::new(row, TABLE_TYPEDEF, file_index);
- let namespace = file.str(key.row as _, key.table as _, 2);
- if namespace.is_empty() {
- continue;
- }
- let name = trim_tick(file.str(key.row as _, key.table as _, 1));
- types.entry(namespace).or_default().entry(name).or_default().push(TypeDef(key));
- }
- for row in 0..file.tables[TABLE_NESTEDCLASS].len {
- let key = Row::new(row, TABLE_NESTEDCLASS, file_index);
- let inner = Row::new(file.usize(key.row as _, key.table as _, 0) - 1, TABLE_TYPEDEF, file_index);
- let outer = Row::new(file.usize(key.row as _, key.table as _, 1) - 1, TABLE_TYPEDEF, file_index);
- let name = file.str(inner.row as _, inner.table as _, 1);
- nested.entry(TypeDef(outer)).or_default().insert(name, TypeDef(inner));
- }
- }
- Self { files, types, nested }
- }
- pub fn tree(&'a self, root: &'a str, filter: &Filter) -> Tree {
- let mut tree = Tree::from_namespace("");
- for ns in self.types.keys() {
- if filter.includes_namespace(ns) {
- tree.insert_namespace(ns, 0);
- }
- }
- if root.is_empty() {
- tree
- } else {
- tree.seek(root).expect("Namespace not found")
- }
- }
-
- //
- // Hash functions for fast type lookup
- //
-
- pub fn namespaces(&self) -> impl Iterator<Item = &str> + '_ {
- self.types.keys().copied()
- }
- pub fn namespace_types(&'a self, namespace: &str, filter: &'a Filter) -> impl Iterator<Item = TypeDef> + '_ {
- self.types.get(namespace).map(move |types| types.values().flatten().copied().filter(move |ty| filter.includes_type(self, *ty))).into_iter().flatten()
- }
- 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 get(&self, type_name: TypeName) -> impl Iterator<Item = TypeDef> + '_ {
- if let Some(types) = self.types.get(type_name.namespace) {
- if let Some(definitions) = types.get(type_name.name) {
- return Some(definitions.iter().copied()).into_iter().flatten();
- }
- }
- None.into_iter().flatten()
- }
- pub fn namespace_functions(&self, namespace: &str) -> impl Iterator<Item = MethodDef> + '_ {
- self.get(TypeName::new(namespace, "Apis")).flat_map(move |apis| self.type_def_methods(apis)).filter(move |method| {
- // The ImplMap table contains import information, without which the function cannot be linked.
- let Some(impl_map) = self.method_def_impl_map(*method) else {
- return false;
- };
-
- // Skip functions exported by ordinal.
- if self.impl_map_import_name(impl_map).starts_with('#') {
- return false;
- }
-
- // If the module name lacks a `.` then it's likely either an inline function, which windows-rs
- // doesn't currently support, or an invalid import library since the extension must be known
- // in order to generate an import table entry unambiguously.
- return self.module_ref_name(self.impl_map_scope(impl_map)).contains('.');
- })
- }
- pub fn namespace_constants(&self, namespace: &str) -> impl Iterator<Item = Field> + '_ {
- self.get(TypeName::new(namespace, "Apis")).flat_map(move |apis| self.type_def_fields(apis))
- }
-
- //
- // Row functions providing low-level file access
- //
-
- fn row_usize(&self, key: Row, column: usize) -> usize {
- self.files[key.file as usize].usize(key.row as _, key.table as _, column)
- }
- fn row_str(&self, key: Row, column: usize) -> &str {
- self.files[key.file as usize].str(key.row as _, key.table as _, column)
- }
- pub fn row_blob(&self, key: Row, column: usize) -> Blob {
- let file = key.file as usize;
- Blob::new(file, self.files[file].blob(key.row as _, key.table as _, column))
- }
- fn row_equal_range(&self, key: Row, table: usize, column: usize, value: usize) -> impl Iterator<Item = Row> {
- let (first, last) = self.files[key.file as usize].equal_range(table, column, value);
- (first..last).map(move |row| Row::new(row, table, key.file as _))
- }
- fn row_attributes(&self, key: Row, source: HasAttribute) -> impl Iterator<Item = Attribute> {
- self.row_equal_range(key, TABLE_CUSTOMATTRIBUTE, 0, source.encode()).map(Attribute)
- }
- fn row_list(&self, key: Row, table: usize, column: usize) -> impl Iterator<Item = Row> {
- let file = key.file as usize;
- let first = self.row_usize(key, column) - 1;
- let last = if key.row + 1 < self.files[file].tables[key.table as usize].len as _ { self.row_usize(key.next(), column) - 1 } else { self.files[file].tables[table].len };
- (first..last).map(move |row| Row::new(row, table, file))
- }
- fn row_decode<T: Decode>(&self, key: Row, column: usize) -> T {
- T::decode(key.file as _, self.row_usize(key, column))
- }
-
- //
- // Attribute table queries
- //
-
- pub fn attribute_name(&self, row: Attribute) -> &str {
- let AttributeType::MemberRef(row) = self.row_decode(row.0, 1);
- let MemberRefParent::TypeRef(row) = self.row_decode(row.0, 0);
- self.type_ref_name(row)
- }
- pub fn attribute_args(&self, row: Attribute) -> Vec<(String, Value)> {
- let AttributeType::MemberRef(member) = self.row_decode(row.0, 1);
- let mut sig = self.member_ref_signature(member);
- let mut values = self.row_blob(row.0, 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, &[]).expect("Type not found") {
- 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::TypeDef(self.get(TypeName::parse(values.read_str())).next().expect("Type not found")),
- Type::TypeDef((def, _)) => Value::Enum(def, values.read_integer(self.type_def_underlying_type(def))),
- _ => unimplemented!(),
- };
-
- 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 {
- 0x02 => Value::Bool(values.read_bool()),
- 0x06 => Value::I16(values.read_i16()),
- 0x08 => Value::I32(values.read_i32()),
- 0x09 => Value::U32(values.read_u32()),
- 0x0E => Value::String(values.read_str().to_string()),
- 0x50 => Value::TypeDef(self.get(TypeName::parse(values.read_str())).next().expect("Type not found")),
- 0x55 => {
- let def = self.get(TypeName::parse(&name)).next().expect("Type not found");
- name = values.read_str().into();
- Value::Enum(def, values.read_integer(self.type_def_underlying_type(def)))
- }
- _ => unimplemented!(),
- };
- args.push((name, arg));
- }
-
- args
- }
-
- //
- // ClassLayout table queries
- //
-
- pub fn class_layout_packing_size(&self, row: ClassLayout) -> usize {
- self.row_usize(row.0, 0)
- }
-
- //
- // Constant table queries
- //
-
- pub fn constant_type(&self, row: Constant) -> Type {
- let code = self.row_usize(row.0, 0);
- Type::from_code(code).expect("Type not found")
- }
- pub fn constant_value(&self, row: Constant) -> Value {
- let mut blob = self.row_blob(row.0, 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()),
- _ => unimplemented!(),
- }
- }
-
- //
- // Field table queries
- //
-
- pub fn field_flags(&self, row: Field) -> FieldAttributes {
- FieldAttributes(self.row_usize(row.0, 0) as _)
- }
- pub fn field_name(&self, row: Field) -> &str {
- self.row_str(row.0, 1)
- }
- pub fn field_constant(&self, row: Field) -> Option<Constant> {
- self.row_equal_range(row.0, TABLE_CONSTANT, 1, HasConstant::Field(row).encode()).map(Constant).next()
- }
- pub fn field_attributes(&self, row: Field) -> impl Iterator<Item = Attribute> {
- self.row_attributes(row.0, HasAttribute::Field(row))
- }
- pub fn field_is_const(&self, row: Field) -> bool {
- self.field_attributes(row).any(|attribute| self.attribute_name(attribute) == "ConstAttribute")
- }
- pub fn field_type(&self, row: Field, enclosing: Option<TypeDef>) -> Type {
- let mut blob = self.row_blob(row.0, 2);
- blob.read_usize();
- blob.read_modifiers();
- let def = self.type_from_blob(&mut blob, enclosing, &[]).expect("Type not found");
-
- if self.field_is_const(row) {
- def.to_const_type().to_const_ptr()
- } else {
- def
- }
- }
- pub fn field_is_blittable(&self, row: Field, enclosing: TypeDef) -> bool {
- self.type_is_blittable(&self.field_type(row, Some(enclosing)))
- }
- pub fn field_is_copyable(&self, row: Field, enclosing: TypeDef) -> bool {
- self.type_is_copyable(&self.field_type(row, Some(enclosing)))
- }
- pub fn field_guid(&self, row: Field) -> Option<GUID> {
- for attribute in self.field_attributes(row) {
- if self.attribute_name(attribute) == "GuidAttribute" {
- return Some(GUID::from_args(&self.attribute_args(attribute)));
- }
- }
- None
- }
- pub fn field_cfg(&self, row: Field) -> Cfg {
- let mut cfg = Cfg::default();
- self.field_cfg_combine(row, None, &mut cfg);
- cfg
- }
- fn field_cfg_combine(&'a self, row: Field, enclosing: Option<TypeDef>, cfg: &mut Cfg<'a>) {
- self.type_cfg_combine(&self.field_type(row, enclosing), cfg)
- }
- pub fn field_is_ansi(&self, row: Field) -> bool {
- for attribute in self.field_attributes(row) {
- if self.attribute_name(attribute) == "NativeEncodingAttribute" {
- if let Some((_, Value::String(encoding))) = self.attribute_args(attribute).get(0) {
- if encoding == "ansi" {
- return true;
- }
- }
- }
- }
- false
- }
-
- //
- // GenericParam table queries
- //
-
- pub fn generic_param_name(&self, row: GenericParam) -> &str {
- self.row_str(row.0, 3)
- }
-
- //
- // ImplMap table queries
- //
-
- pub fn impl_map_flags(&self, row: ImplMap) -> PInvokeAttributes {
- PInvokeAttributes(self.row_usize(row.0, 0))
- }
- pub fn impl_map_scope(&self, row: ImplMap) -> ModuleRef {
- ModuleRef(Row::new(self.row_usize(row.0, 3) - 1, TABLE_MODULEREF, row.0.file as _))
- }
- pub fn impl_map_import_name(&self, row: ImplMap) -> &str {
- self.row_str(row.0, 2)
- }
-
- //
- // InterfaceImpl table queries
- //
-
- pub fn interface_impl_attributes(&self, row: InterfaceImpl) -> impl Iterator<Item = Attribute> {
- self.row_attributes(row.0, HasAttribute::InterfaceImpl(row))
- }
- pub fn interface_impl_is_default(&self, row: InterfaceImpl) -> bool {
- self.interface_impl_attributes(row).any(|attribute| self.attribute_name(attribute) == "DefaultAttribute")
- }
- pub fn interface_impl_is_overridable(&self, row: InterfaceImpl) -> bool {
- self.interface_impl_attributes(row).any(|attribute| self.attribute_name(attribute) == "OverridableAttribute")
- }
- pub fn interface_impl_type(&self, row: InterfaceImpl, generics: &[Type]) -> Interface {
- let mut kind = InterfaceKind::None;
- for attribute in self.interface_impl_attributes(row) {
- match self.attribute_name(attribute) {
- "DefaultAttribute" => kind = InterfaceKind::Default,
- "OverridableAttribute" => kind = InterfaceKind::Overridable,
- _ => {}
- }
- }
- Interface { ty: self.type_from_ref(self.row_decode(row.0, 1), None, generics), kind }
- }
-
- //
- // MemberRef table queries
- //
-
- pub fn member_ref_parent(&self, row: MemberRef) -> MemberRefParent {
- self.row_decode(row.0, 0)
- }
- pub fn member_ref_signature(&self, row: MemberRef) -> Blob {
- self.row_blob(row.0, 2)
- }
-
- //
- // MethodDef table queries
- //
-
- pub fn method_def_impl_flags(&self, row: MethodDef) -> MethodImplAttributes {
- MethodImplAttributes(self.row_usize(row.0, 1))
- }
- pub fn method_def_flags(&self, row: MethodDef) -> MethodAttributes {
- MethodAttributes(self.row_usize(row.0, 2) as _)
- }
- pub fn method_def_name(&self, row: MethodDef) -> &str {
- self.row_str(row.0, 3)
- }
- pub fn method_def_params(&self, row: MethodDef) -> impl Iterator<Item = Param> {
- self.row_list(row.0, TABLE_PARAM, 5).map(Param)
- }
- pub fn method_def_attributes(&self, row: MethodDef) -> impl Iterator<Item = Attribute> {
- self.row_attributes(row.0, HasAttribute::MethodDef(row))
- }
- pub fn method_def_is_deprecated(&self, row: MethodDef) -> bool {
- self.method_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "DeprecatedAttribute")
- }
- pub fn method_def_does_not_return(&self, row: MethodDef) -> bool {
- self.method_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "DoesNotReturnAttribute")
- }
- pub fn method_def_can_return_multiple_success_values(&self, row: MethodDef) -> bool {
- self.method_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "CanReturnMultipleSuccessValuesAttribute")
- }
- pub fn method_def_special_name(&self, row: MethodDef) -> String {
- let name = self.method_def_name(row);
- if self.method_def_flags(row).contains(MethodAttributes::SPECIAL) {
- if name.starts_with("get") {
- name[4..].to_string()
- } else if name.starts_with("put") {
- format!("Set{}", &name[4..])
- } else if name.starts_with("add") {
- name[4..].to_string()
- } else if name.starts_with("remove") {
- format!("Remove{}", &name[7..])
- } else {
- name.to_string()
- }
- } else {
- for attribute in self.method_def_attributes(row) {
- if self.attribute_name(attribute) == "OverloadAttribute" {
- for (_, arg) in self.attribute_args(attribute) {
- if let Value::String(name) = arg {
- return name;
- }
- }
- }
- }
- name.to_string()
- }
- }
- pub fn method_def_static_lib(&self, row: MethodDef) -> Option<String> {
- for attribute in self.method_def_attributes(row) {
- if self.attribute_name(attribute) == "StaticLibraryAttribute" {
- let args = self.attribute_args(attribute);
- if let Value::String(value) = &args[0].1 {
- return Some(value.clone());
- }
- }
- }
- None
- }
- pub fn method_def_impl_map(&self, row: MethodDef) -> Option<ImplMap> {
- self.row_equal_range(row.0, TABLE_IMPLMAP, 1, MemberForwarded::MethodDef(row).encode()).map(ImplMap).next()
- }
- pub fn method_def_module_name(&self, row: MethodDef) -> String {
- 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()
- }
- pub fn method_def_signature(&self, row: MethodDef, generics: &[Type]) -> Signature {
- let mut blob = self.row_blob(row.0, 4);
- blob.read_usize();
- blob.read_usize();
-
- let mut return_type = self.type_from_blob(&mut blob, None, generics);
-
- let mut params: Vec<SignatureParam> = self
- .method_def_params(row)
- .filter_map(|param| {
- if self.param_sequence(param) == 0 {
- if self.param_is_const(param) {
- return_type = return_type.clone().map(|ty| ty.to_const_type());
- }
- None
- } else {
- let is_output = self.param_flags(param).contains(ParamAttributes::OUTPUT);
- let mut ty = self.type_from_blob(&mut blob, None, generics).expect("Parameter type not found");
- if self.param_is_const(param) || !is_output {
- ty = ty.to_const_type();
- }
- if !is_output {
- ty = ty.to_const_ptr();
- }
- let kind = self.param_kind(param);
- Some(SignatureParam { def: param, ty, kind })
- }
- })
- .collect();
-
- for position in 0..params.len() {
- // Point len params back to the corresponding ptr params.
- match params[position].kind {
- SignatureParamKind::ArrayRelativeLen(relative) | SignatureParamKind::ArrayRelativeByteLen(relative) => {
- // The len params must be input only.
- if !self.param_flags(params[relative].def).contains(ParamAttributes::OUTPUT) && position != relative && !params[relative].ty.is_pointer() {
- params[relative].kind = SignatureParamKind::ArrayRelativePtr(position);
- } else {
- params[position].kind = SignatureParamKind::Other;
- }
- }
- SignatureParamKind::ArrayFixed(_) => {
- if self.param_free_with(params[position].def).is_some() {
- params[position].kind = SignatureParamKind::Other;
- }
- }
- _ => {}
- }
- }
-
- let mut sets = BTreeMap::<usize, Vec<usize>>::new();
-
- // Finds sets of ptr params pointing at the same len param.
- for (position, param) in params.iter().enumerate() {
- match param.kind {
- SignatureParamKind::ArrayRelativeLen(relative) | SignatureParamKind::ArrayRelativeByteLen(relative) => {
- sets.entry(relative).or_default().push(position);
- }
- _ => {}
- }
- }
-
- // Remove all sets.
- for (len, ptrs) in sets {
- if ptrs.len() > 1 {
- params[len].kind = SignatureParamKind::Other;
- for ptr in ptrs {
- params[ptr].kind = SignatureParamKind::Other;
- }
- }
- }
-
- // Remove any byte arrays that aren't byte-sized types.
- for position in 0..params.len() {
- if let SignatureParamKind::ArrayRelativeByteLen(relative) = params[position].kind {
- if !params[position].ty.is_byte_size() {
- params[position].kind = SignatureParamKind::Other;
- params[relative].kind = SignatureParamKind::Other;
- }
- }
- }
-
- for param in &mut params {
- if param.kind == SignatureParamKind::Other {
- if self.signature_param_is_convertible(param) {
- if self.signature_param_is_failible_param(param) {
- param.kind = SignatureParamKind::TryInto;
- } else {
- param.kind = SignatureParamKind::IntoParam;
- }
- } else {
- let flags = self.param_flags(param.def);
- if param.ty.is_pointer() && (flags.contains(ParamAttributes::OPTIONAL) || self.param_is_reserved(param.def)) {
- param.kind = SignatureParamKind::OptionalPointer;
- } else if self.type_is_primitive(&param.ty) && (!param.ty.is_pointer() || self.type_is_blittable(&param.ty.deref())) {
- param.kind = SignatureParamKind::ValueType;
- } else if self.type_is_blittable(&param.ty) {
- param.kind = SignatureParamKind::Blittable;
- }
- }
- }
- }
-
- Signature { def: row, params, return_type }
- }
- pub fn method_def_extern_abi(&self, def: MethodDef) -> &'static str {
- let impl_map = self.method_def_impl_map(def).expect("ImplMap not found");
- let flags = self.impl_map_flags(impl_map);
-
- if flags.contains(PInvokeAttributes::CONV_PLATFORM) {
- "system"
- } else if flags.contains(PInvokeAttributes::CONV_CDECL) {
- "cdecl"
- } else {
- unimplemented!()
- }
- }
- pub fn method_def_size(&self, method: MethodDef) -> usize {
- let signature = self.method_def_signature(method, &[]);
- signature.params.iter().fold(0, |sum, param| sum + std::cmp::max(4, self.type_size(&param.ty)))
- }
- 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::EXPLICIT_LAYOUT) {
- 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_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,
- _ => 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,
- }
- }
-
- //
- // ModuleRef table queries
- //
-
- fn module_ref_name(&self, row: ModuleRef) -> &str {
- self.row_str(row.0, 0)
- }
-
- //
- // Param table queries
- //
-
- pub fn param_flags(&self, row: Param) -> ParamAttributes {
- ParamAttributes(self.row_usize(row.0, 0) as _)
- }
- pub fn param_sequence(&self, row: Param) -> usize {
- self.row_usize(row.0, 1)
- }
- pub fn param_name(&self, row: Param) -> &str {
- self.row_str(row.0, 2)
- }
- pub fn param_attributes(&self, row: Param) -> impl Iterator<Item = Attribute> {
- self.row_attributes(row.0, HasAttribute::Param(row))
- }
- pub fn param_is_com_out_ptr(&self, row: Param) -> bool {
- self.param_attributes(row).any(|attribute| self.attribute_name(attribute) == "ComOutPtrAttribute")
- }
- fn param_kind(&self, row: Param) -> SignatureParamKind {
- for attribute in self.param_attributes(row) {
- match self.attribute_name(attribute) {
- "NativeArrayInfoAttribute" => {
- for (_, value) in self.attribute_args(attribute) {
- match value {
- Value::I16(value) => return SignatureParamKind::ArrayRelativeLen(value as _),
- Value::I32(value) => return SignatureParamKind::ArrayFixed(value as _),
- _ => {}
- }
- }
- }
- "MemorySizeAttribute" => {
- for (_, value) in self.attribute_args(attribute) {
- if let Value::I16(value) = value {
- return SignatureParamKind::ArrayRelativeByteLen(value as _);
- }
- }
- }
- _ => {}
- }
- }
- SignatureParamKind::Other
- }
- pub fn param_is_retval(&self, row: Param) -> bool {
- self.param_attributes(row).any(|attribute| self.attribute_name(attribute) == "RetValAttribute")
- }
- pub fn param_is_reserved(&self, row: Param) -> bool {
- self.param_attributes(row).any(|attribute| self.attribute_name(attribute) == "ReservedAttribute")
- }
- pub fn param_free_with(&self, row: Param) -> Option<String> {
- for attribute in self.param_attributes(row) {
- if self.attribute_name(attribute) == "FreeWithAttribute" {
- for (_, arg) in self.attribute_args(attribute) {
- if let Value::String(name) = arg {
- return Some(name);
- }
- }
- }
- }
- None
- }
- pub fn param_is_const(&self, row: Param) -> bool {
- self.param_attributes(row).any(|attribute| self.attribute_name(attribute) == "ConstAttribute")
- }
-
- //
- // TypeDef table queries
- //
-
- pub fn type_def_flags(&self, row: TypeDef) -> TypeAttributes {
- TypeAttributes(self.row_usize(row.0, 0) as _)
- }
- pub fn type_def_name(&self, row: TypeDef) -> &str {
- self.row_str(row.0, 1)
- }
- pub fn type_def_namespace(&self, row: TypeDef) -> &str {
- self.row_str(row.0, 2)
- }
- 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_extends(&self, row: TypeDef) -> TypeName {
- self.type_def_or_ref(self.row_decode(row.0, 3))
- }
- pub fn type_def_fields(&self, row: TypeDef) -> impl Iterator<Item = Field> {
- self.row_list(row.0, TABLE_FIELD, 4).map(Field)
- }
- pub fn type_def_methods(&self, row: TypeDef) -> impl Iterator<Item = MethodDef> {
- self.row_list(row.0, TABLE_METHODDEF, 5).map(MethodDef)
- }
- pub fn type_def_attributes(&self, row: TypeDef) -> impl Iterator<Item = Attribute> {
- self.row_attributes(row.0, HasAttribute::TypeDef(row))
- }
- pub fn type_def_generics(&self, row: TypeDef) -> impl Iterator<Item = Type> {
- self.row_equal_range(row.0, TABLE_GENERICPARAM, 2, TypeOrMethodDef::TypeDef(row).encode()).map(|row| Type::GenericParam(GenericParam(row)))
- }
- pub fn type_def_interface_impls(&self, row: TypeDef) -> impl Iterator<Item = InterfaceImpl> {
- self.row_equal_range(row.0, TABLE_INTERFACEIMPL, 0, (row.0.row + 1) as _).map(InterfaceImpl)
- }
- pub fn type_def_enclosing_type(&self, row: TypeDef) -> Option<TypeDef> {
- self.row_equal_range(row.0, TABLE_NESTEDCLASS, 0, (row.0.row + 1) as _).next().map(|row| TypeDef(Row::new(self.files[row.file as usize].usize(row.row as _, row.table as _, 1) - 1, TABLE_TYPEDEF, row.file as _)))
- }
- pub fn type_def_class_layout(&self, row: TypeDef) -> Option<ClassLayout> {
- self.row_equal_range(row.0, TABLE_CLASSLAYOUT, 2, (row.0.row + 1) as _).map(ClassLayout).next()
- }
- 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 {
- if self.type_def_flags(row).contains(TypeAttributes::INTERFACE) {
- TypeKind::Interface
- } else {
- match self.type_def_extends(row) {
- TypeName::Enum => TypeKind::Enum,
- TypeName::Delegate => TypeKind::Delegate,
- TypeName::Struct => TypeKind::Struct,
- _ => TypeKind::Class,
- }
- }
- }
- pub fn type_def_stdcall(&self, row: TypeDef) -> usize {
- if self.type_def_kind(row) == TypeKind::Struct {
- if self.type_def_flags(row).contains(TypeAttributes::EXPLICIT_LAYOUT) {
- self.type_def_fields(row).map(|field| self.type_stdcall(&self.field_type(field, Some(row)))).max().unwrap_or(1)
- } else {
- self.type_def_fields(row).fold(0, |sum, field| sum + self.type_stdcall(&self.field_type(field, Some(row))))
- }
- } else {
- 4
- }
- }
- pub fn type_def_is_blittable(&self, row: TypeDef) -> bool {
- match self.type_def_kind(row) {
- TypeKind::Struct => {
- if self.type_def_flags(row).contains(TypeAttributes::WINRT) {
- self.type_def_fields(row).all(|field| self.field_is_blittable(field, row))
- } else {
- true
- }
- }
- TypeKind::Enum => true,
- TypeKind::Delegate => !self.type_def_flags(row).contains(TypeAttributes::WINRT),
- _ => false,
- }
- }
- pub fn type_def_is_copyable(&self, row: TypeDef) -> bool {
- match self.type_def_kind(row) {
- TypeKind::Struct => self.type_def_fields(row).all(|field| self.field_is_copyable(field, row)),
- TypeKind::Enum => true,
- TypeKind::Delegate => !self.type_def_flags(row).contains(TypeAttributes::WINRT),
- _ => false,
- }
- }
- pub fn type_def_is_callback(&self, row: TypeDef) -> bool {
- !self.type_def_flags(row).contains(TypeAttributes::WINRT) && self.type_def_kind(row) == TypeKind::Delegate
- }
- pub fn type_def_has_default_constructor(&self, row: TypeDef) -> bool {
- for attribute in self.type_def_attributes(row) {
- if self.attribute_name(attribute) == "ActivatableAttribute" {
- if self.attribute_args(attribute).iter().any(|arg| matches!(arg.1, Value::TypeDef(_))) {
- continue;
- } else {
- return true;
- }
- }
- }
- false
- }
- // TODO: consider removing all the expects and just return Option<T> and let the bindgen crate expect it
- // that way the metadata reader is a little more schema-agnostic...
- pub fn type_def_invoke_method(&self, row: TypeDef) -> MethodDef {
- self.type_def_methods(row).find(|method| self.method_def_name(*method) == "Invoke").expect("`Invoke` method not found")
- }
- pub fn type_def_interfaces(&'a self, row: TypeDef, generics: &'a [Type]) -> impl Iterator<Item = Interface> + '_ {
- self.type_def_interface_impls(row).map(move |row| self.interface_impl_type(row, generics))
- }
- pub fn type_def_default_interface(&self, row: TypeDef) -> Option<Type> {
- self.type_def_interfaces(row, &[]).find(|interface| interface.kind == InterfaceKind::Default).map(|interface| interface.ty)
- }
- pub fn type_def_has_default_interface(&self, row: TypeDef) -> bool {
- self.type_def_interface_impls(row).any(|imp| self.interface_impl_is_default(imp))
- }
- pub fn type_def_is_deprecated(&self, row: TypeDef) -> bool {
- self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "DeprecatedAttribute")
- }
- pub fn type_def_is_handle(&self, row: TypeDef) -> bool {
- self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "NativeTypedefAttribute")
- }
- pub fn type_def_is_exclusive(&self, row: TypeDef) -> bool {
- self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "ExclusiveToAttribute")
- }
- pub fn type_def_is_scoped(&self, row: TypeDef) -> bool {
- self.type_def_flags(row).contains(TypeAttributes::WINRT) || self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "ScopedEnumAttribute")
- }
- pub fn type_def_is_contract(&self, row: TypeDef) -> bool {
- self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "ApiContractAttribute")
- }
- fn type_def_is_composable(&self, row: TypeDef) -> bool {
- self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "ComposableAttribute")
- }
- fn type_def_is_struct(&self, row: TypeDef) -> bool {
- // This check is used to detect virtual functions that return C-style PODs that affect how the stack is packed for x86.
- // It could be defined as a struct with more than one field but that check is complicated as it would have to detect
- // nested structs. Fortunately, this is rare enough that this check is sufficient.
- self.type_def_kind(row) == TypeKind::Struct && !self.type_def_is_handle(row)
- }
- fn type_def_is_borrowed(&self, row: TypeDef) -> bool {
- match self.type_def_kind(row) {
- TypeKind::Class => self.type_def_is_composable(row),
- TypeKind::Delegate => false,
- _ => !self.type_def_is_blittable(row),
- }
- }
- pub fn type_def_is_trivially_convertible(&self, row: TypeDef) -> bool {
- match self.type_def_kind(row) {
- TypeKind::Struct => self.type_def_is_handle(row),
- _ => false,
- }
- }
- pub fn type_def_is_primitive(&self, row: TypeDef) -> bool {
- match self.type_def_kind(row) {
- TypeKind::Enum => true,
- TypeKind::Struct => self.type_def_is_handle(row),
- TypeKind::Delegate => !self.type_def_flags(row).contains(TypeAttributes::WINRT),
- _ => false,
- }
- }
- pub fn type_def_has_explicit_layout(&self, row: TypeDef) -> bool {
- if self.type_def_kind(row) != TypeKind::Struct {
- return false;
- }
- fn check(reader: &Reader, row: TypeDef) -> bool {
- if reader.type_def_flags(row).contains(TypeAttributes::EXPLICIT_LAYOUT) {
- return true;
- }
- if reader.type_def_fields(row).any(|field| reader.type_has_explicit_layout(&reader.field_type(field, Some(row)))) {
- return true;
- }
- false
- }
- let type_name = self.type_def_type_name(row);
- if type_name.namespace.is_empty() {
- check(self, row)
- } else {
- for row in self.get(type_name) {
- if check(self, row) {
- return true;
- }
- }
- false
- }
- }
- pub fn type_def_has_packing(&self, row: TypeDef) -> bool {
- if self.type_def_kind(row) != TypeKind::Struct {
- return false;
- }
- fn check(reader: &Reader, row: TypeDef) -> bool {
- if reader.type_def_class_layout(row).is_some() {
- return true;
- }
- if reader.type_def_fields(row).any(|field| reader.type_has_packing(&reader.field_type(field, Some(row)))) {
- return true;
- }
- false
- }
- let type_name = self.type_def_type_name(row);
- if type_name.namespace.is_empty() {
- check(self, row)
- } else {
- for row in self.get(type_name) {
- if check(self, row) {
- return true;
- }
- }
- false
- }
- }
- pub fn type_def_has_callback(&self, row: TypeDef) -> bool {
- if self.type_def_is_callback(row) {
- return true;
- }
- if self.type_def_kind(row) != TypeKind::Struct {
- return false;
- }
- fn check(reader: &Reader, row: TypeDef) -> bool {
- if reader.type_def_fields(row).any(|field| reader.type_has_callback(&reader.field_type(field, Some(row)))) {
- return true;
- }
- false
- }
- let type_name = self.type_def_type_name(row);
- if type_name.namespace.is_empty() {
- check(self, row)
- } else {
- for row in self.get(type_name) {
- if check(self, row) {
- return true;
- }
- }
- false
- }
- }
- pub fn type_def_guid(&self, row: TypeDef) -> Option<GUID> {
- for attribute in self.type_def_attributes(row) {
- if self.attribute_name(attribute) == "GuidAttribute" {
- return Some(GUID::from_args(&self.attribute_args(attribute)));
- }
- }
- None
- }
- pub fn type_def_bases(&self, mut row: TypeDef) -> Vec<TypeDef> {
- // TODO: maybe return Vec<Type>
- let mut bases = Vec::new();
- loop {
- let extends = self.type_def_extends(row);
- if extends == TypeName::Object {
- break;
- } else {
- row = self.get(extends).next().expect("Type not found");
- bases.push(row);
- }
- }
- bases
- }
- pub fn type_def_is_flags(&self, row: TypeDef) -> bool {
- // Win32 enums use the Flags attribute. WinRT enums don't have the Flags attribute but are paritioned merely based
- // on whether they are signed.
- self.type_def_attributes(row).any(|attribute| self.attribute_name(attribute) == "FlagsAttribute") || (self.type_def_flags(row).contains(TypeAttributes::WINRT) && self.type_def_underlying_type(row) == Type::U32)
- }
- pub fn type_def_is_agile(&self, row: TypeDef) -> bool {
- for attribute in self.type_def_attributes(row) {
- match self.attribute_name(attribute) {
- "AgileAttribute" => return true,
- "MarshalingBehaviorAttribute" => {
- if let Some((_, Value::Enum(_, Integer::I32(2)))) = self.attribute_args(attribute).get(0) {
- return true;
- }
- }
- _ => {}
- }
- }
- matches!(self.type_def_type_name(row), TypeName::IAsyncAction | TypeName::IAsyncActionWithProgress | TypeName::IAsyncOperation | TypeName::IAsyncOperationWithProgress)
- }
- pub fn type_def_invalid_values(&self, row: TypeDef) -> Vec<i64> {
- let mut values = Vec::new();
- for attribute in self.type_def_attributes(row) {
- if self.attribute_name(attribute) == "InvalidHandleValueAttribute" {
- if let Some((_, Value::I64(value))) = self.attribute_args(attribute).get(0) {
- values.push(*value);
- }
- }
- }
- values
- }
- pub fn type_def_usable_for(&self, row: TypeDef) -> Option<TypeDef> {
- for attribute in self.type_def_attributes(row) {
- if self.attribute_name(attribute) == "AlsoUsableForAttribute" {
- if let Some((_, Value::String(name))) = self.attribute_args(attribute).get(0) {
- return self.get(TypeName::new(self.type_def_namespace(row), name.as_str())).next();
- }
- }
- }
- None
- }
- pub fn type_def_is_nullable(&self, row: TypeDef) -> bool {
- match self.type_def_kind(row) {
- TypeKind::Interface | TypeKind::Class => true,
- // TODO: win32 callbacks should be nullable...
- TypeKind::Delegate => self.type_def_flags(row).contains(TypeAttributes::WINRT),
- _ => false,
- }
- }
- pub fn type_def_can_implement(&self, row: TypeDef) -> bool {
- for attribute in self.type_def_attributes(row) {
- if self.attribute_name(attribute) == "ExclusiveToAttribute" {
- for (_, arg) in self.attribute_args(attribute) {
- if let Value::TypeDef(def) = arg {
- for child in self.type_def_interfaces(def, &[]) {
- if child.kind == InterfaceKind::Overridable {
- if let Type::TypeDef((def, _)) = child.ty {
- if self.type_def_type_name(def) == self.type_def_type_name(row) {
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
- }
- true
- }
- pub fn type_def_async_kind(&self, row: TypeDef) -> AsyncKind {
- match self.type_def_type_name(row) {
- TypeName::IAsyncAction => AsyncKind::Action,
- TypeName::IAsyncActionWithProgress => AsyncKind::ActionWithProgress,
- TypeName::IAsyncOperation => AsyncKind::Operation,
- TypeName::IAsyncOperationWithProgress => AsyncKind::OperationWithProgress,
- _ => AsyncKind::None,
- }
- }
- pub fn type_def_signature(&self, row: TypeDef, generics: &[Type]) -> String {
- match self.type_def_kind(row) {
- TypeKind::Interface => self.type_def_interface_signature(row, generics),
- TypeKind::Class => {
- if let Type::TypeDef((default, generics)) = self.type_def_interfaces(row, generics).find(|row| row.kind == InterfaceKind::Default).expect("Default interface not found").ty {
- format!("rc({};{})", self.type_def_type_name(row), self.type_def_interface_signature(default, &generics))
- } else {
- unimplemented!();
- }
- }
- TypeKind::Enum => format!("enum({};{})", self.type_def_type_name(row), self.type_signature(&self.type_def_underlying_type(row))),
- TypeKind::Struct => {
- let mut result = format!("struct({}", self.type_def_type_name(row));
- for field in self.type_def_fields(row) {
- result.push(';');
- result.push_str(&self.type_signature(&self.field_type(field, Some(row))));
- }
- result.push(')');
- result
- }
- TypeKind::Delegate => {
- if generics.is_empty() {
- format!("delegate({})", self.type_def_interface_signature(row, generics))
- } else {
- self.type_def_interface_signature(row, generics)
- }
- }
- }
- }
- fn type_def_interface_signature(&self, row: TypeDef, generics: &[Type]) -> String {
- let guid = self.type_def_guid(row).unwrap();
- if generics.is_empty() {
- format!("{{{guid:#?}}}")
- } else {
- let mut result = format!("pinterface({{{guid:#?}}}");
- for generic in generics {
- result.push(';');
- result.push_str(&self.type_signature(generic));
- }
- result.push(')');
- result
- }
- }
- pub fn type_def_cfg(&self, row: TypeDef, generics: &[Type]) -> Cfg {
- let mut cfg = Cfg::default();
- self.type_def_cfg_combine(row, generics, &mut cfg);
- self.cfg_add_attributes(&mut cfg, self.type_def_attributes(row));
- cfg
- }
- pub fn type_def_cfg_impl(&self, def: TypeDef, generics: &[Type]) -> Cfg {
- let mut cfg = Cfg { implement: true, ..Default::default() };
-
- fn combine<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) {
- reader.type_def_cfg_combine(def, generics, cfg);
-
- for method in reader.type_def_methods(def) {
- reader.signature_cfg_combine(&reader.method_def_signature(method, generics), cfg);
- }
- }
-
- combine(self, def, generics, &mut cfg);
-
- for def in self.type_def_vtables(def) {
- if let Type::TypeDef((def, generics)) = def {
- combine(self, def, &generics, &mut cfg);
- }
- }
-
- if self.type_def_flags(def).contains(TypeAttributes::WINRT) {
- for interface in self.type_def_interfaces(def, generics) {
- if let Type::TypeDef((def, generics)) = interface.ty {
- combine(self, def, &generics, &mut cfg);
- }
- }
- }
-
- self.cfg_add_attributes(&mut cfg, self.type_def_attributes(def));
- cfg
- }
- pub fn type_def_cfg_combine(&'a self, row: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) {
- for generic in generics {
- self.type_cfg_combine(generic, cfg);
- }
-
- if cfg.types.entry(self.type_def_namespace(row)).or_default().insert(row) {
- match self.type_def_kind(row) {
- TypeKind::Class => {
- if let Some(default_interface) = self.type_def_default_interface(row) {
- self.type_cfg_combine(&default_interface, cfg);
- }
- }
- TypeKind::Interface => {
- if !self.type_def_flags(row).contains(TypeAttributes::WINRT) {
- for def in self.type_def_vtables(row) {
- if let Type::TypeDef((def, _)) = def {
- cfg.add_feature(self.type_def_namespace(def));
- }
- }
- }
- }
- TypeKind::Struct => {
- self.type_def_fields(row).for_each(|field| self.field_cfg_combine(field, Some(row), cfg));
- let type_name = self.type_def_type_name(row);
- if !type_name.namespace.is_empty() {
- for def in self.get(type_name) {
- if def != row {
- self.type_def_cfg_combine(def, &[], cfg);
- }
- }
- }
- }
- TypeKind::Delegate => self.signature_cfg_combine(&self.method_def_signature(self.type_def_invoke_method(row), generics), cfg),
- _ => {}
- }
- }
- }
- pub fn type_def_vtables(&self, row: TypeDef) -> Vec<Type> {
- let mut result = Vec::new();
- if self.type_def_flags(row).contains(TypeAttributes::WINRT) {
- result.push(Type::IUnknown);
- if self.type_def_kind(row) != TypeKind::Delegate {
- result.push(Type::IInspectable);
- }
- } else {
- let mut next = row;
- while let Some(base) = self.type_def_interfaces(next, &[]).next() {
- match base.ty {
- Type::TypeDef((row, _)) => {
- next = row;
- result.insert(0, base.ty);
- }
- Type::IInspectable => {
- result.insert(0, Type::IUnknown);
- result.insert(1, Type::IInspectable);
- break;
- }
- Type::IUnknown => {
- result.insert(0, Type::IUnknown);
- break;
- }
- _ => unimplemented!(),
- }
- }
- }
- result
- }
-
- //
- // TypeRef table queries
- //
-
- pub fn type_ref_name(&self, row: TypeRef) -> &str {
- self.row_str(row.0, 1)
- }
- pub fn type_ref_namespace(&self, row: TypeRef) -> &str {
- self.row_str(row.0, 2)
- }
- pub fn type_ref_type_name(&self, row: TypeRef) -> TypeName {
- TypeName::new(self.type_ref_name(row), self.type_ref_namespace(row))
- }
-
- //
- // TypeSpec table queries
- //
-
- pub fn type_spec_signature(&self, row: TypeSpec) -> Blob {
- self.row_blob(row.0, 0)
- }
-
- //
- // Signature queries
- //
-
- pub fn signature_cfg(&self, signature: &Signature) -> Cfg {
- let mut cfg = Cfg::default();
- self.signature_cfg_combine(signature, &mut cfg);
- self.cfg_add_attributes(&mut cfg, self.method_def_attributes(signature.def));
- cfg
- }
- fn signature_cfg_combine(&'a self, signature: &Signature, cfg: &mut Cfg<'a>) {
- signature.return_type.iter().for_each(|ty| self.type_cfg_combine(ty, cfg));
- signature.params.iter().for_each(|param| self.type_cfg_combine(&param.ty, cfg));
- }
- pub fn signature_param_is_borrowed(&self, param: &SignatureParam) -> bool {
- self.type_is_borrowed(&param.ty)
- }
- pub fn signature_param_is_failible_param(&self, param: &SignatureParam) -> bool {
- self.type_is_non_exclusive_winrt_interface(&param.ty)
- }
- pub fn signature_param_is_trivially_convertible(&self, param: &SignatureParam) -> bool {
- self.type_is_trivially_convertible(&param.ty)
- }
- pub fn signature_param_is_convertible(&self, param: &SignatureParam) -> bool {
- !self.param_flags(param.def).contains(ParamAttributes::OUTPUT) && !param.ty.is_winrt_array() && !param.ty.is_pointer() && !param.kind.is_array() && (self.type_is_borrowed(&param.ty) || self.type_is_non_exclusive_winrt_interface(&param.ty) || self.type_is_trivially_convertible(&param.ty))
- }
- pub fn signature_param_is_retval(&self, param: &SignatureParam) -> bool {
- // The Win32 metadata uses `RetValAttribute` to call out retval methods but it is employed
- // very sparingly, so this heuristic is used to apply the transformation more uniformly.
- if self.param_is_retval(param.def) {
- return true;
- }
- if !param.ty.is_pointer() {
- return false;
- }
- if param.ty.is_void() {
- return false;
- }
- let flags = self.param_flags(param.def);
- if flags.contains(ParamAttributes::INPUT) || !flags.contains(ParamAttributes::OUTPUT) || flags.contains(ParamAttributes::OPTIONAL) || param.kind.is_array() {
- return false;
- }
- if self.param_kind(param.def).is_array() {
- return false;
- }
- // If it's bigger than 128 bits, best to pass as a reference.
- if self.type_size(&param.ty.deref()) > 16 {
- return false;
- }
- // TODO: find a way to treat this like COM interface result values.
- !self.type_is_callback(&param.ty.deref())
- }
- pub fn signature_kind(&self, signature: &Signature) -> SignatureKind {
- if self.method_def_can_return_multiple_success_values(signature.def) {
- return SignatureKind::PreserveSig;
- }
- if let Some(return_type) = &signature.return_type {
- match return_type {
- Type::HRESULT => {
- if signature.params.len() >= 2 {
- if let Some(guid) = self.signature_param_is_query_guid(&signature.params) {
- if let Some(object) = self.signature_param_is_query_object(&signature.params) {
- if self.param_flags(signature.params[object].def).contains(ParamAttributes::OPTIONAL) {
- return SignatureKind::QueryOptional(QueryPosition { object, guid });
- } else {
- return SignatureKind::Query(QueryPosition { object, guid });
- }
- }
- }
- }
-
- if self.signature_is_retval(signature) {
- return SignatureKind::ResultValue;
- }
-
- return SignatureKind::ResultVoid;
- }
- Type::TypeDef((def, _)) if self.type_def_type_name(*def) == TypeName::NTSTATUS => {
- return SignatureKind::ResultVoid;
- }
- _ if self.type_is_struct(return_type) => {
- return SignatureKind::ReturnStruct;
- }
- _ => return SignatureKind::PreserveSig,
- }
- }
-
- if self.signature_is_retval(signature) {
- return SignatureKind::ReturnValue;
- }
-
- SignatureKind::ReturnVoid
- }
- fn signature_is_retval(&self, signature: &Signature) -> bool {
- signature.params.last().map_or(false, |param| self.signature_param_is_retval(param))
- && signature.params[..signature.params.len() - 1].iter().all(|param| {
- let flags = self.param_flags(param.def);
- !flags.contains(ParamAttributes::OUTPUT)
- })
- }
- fn signature_param_is_query_guid(&self, params: &[SignatureParam]) -> Option<usize> {
- params.iter().rposition(|param| param.ty == Type::ConstPtr((Box::new(Type::GUID), 1)) && !self.param_flags(param.def).contains(ParamAttributes::OUTPUT))
- }
- fn signature_param_is_query_object(&self, params: &[SignatureParam]) -> Option<usize> {
- params.iter().rposition(|param| param.ty == Type::MutPtr((Box::new(Type::Void), 2)) && self.param_is_com_out_ptr(param.def))
- }
-
- //
- // Other type queries
- //
-
- fn cfg_add_attributes(&self, cfg: &mut Cfg, attributes: impl Iterator<Item = Attribute>) {
- for attribute in attributes {
- match self.attribute_name(attribute) {
- "SupportedArchitectureAttribute" => {
- if let Some((_, Value::Enum(_, Integer::I32(value)))) = self.attribute_args(attribute).get(0) {
- if value & 1 == 1 {
- cfg.arches.insert("x86");
- }
- if value & 2 == 2 {
- cfg.arches.insert("x86_64");
- }
- if value & 4 == 4 {
- cfg.arches.insert("aarch64");
- }
- }
- }
- "DeprecatedAttribute" => {
- cfg.add_feature("deprecated");
- }
- _ => {}
- }
- }
- }
- pub fn type_cfg(&self, ty: &Type) -> Cfg {
- let mut cfg = Cfg::default();
- self.type_cfg_combine(ty, &mut cfg);
- cfg
- }
- pub fn type_cfg_combine(&'a self, ty: &Type, cfg: &mut Cfg<'a>) {
- match ty {
- Type::TypeDef((row, generics)) => self.type_def_cfg_combine(*row, generics, cfg),
- Type::Win32Array((ty, _)) => self.type_cfg_combine(ty, cfg),
- Type::ConstPtr((ty, _)) => self.type_cfg_combine(ty, cfg),
- Type::MutPtr((ty, _)) => self.type_cfg_combine(ty, cfg),
- Type::WinrtArray(ty) => self.type_cfg_combine(ty, cfg),
- Type::WinrtArrayRef(ty) => self.type_cfg_combine(ty, cfg),
- ty => _ = cfg.core_types.insert(ty.clone()),
- }
- }
- pub fn type_interfaces(&self, ty: &Type) -> Vec<Interface> {
- // TODO: collect into btree map and then return collected vec
- // This will both sort the results and should make finding dupes faster
- fn walk(reader: &Reader, result: &mut Vec<Interface>, parent: &Type, is_base: bool) {
- if let Type::TypeDef((row, generics)) = parent {
- for mut child in reader.type_def_interfaces(*row, generics) {
- child.kind = if !is_base && child.kind == InterfaceKind::Default {
- InterfaceKind::Default
- } else if child.kind == InterfaceKind::Overridable {
- continue;
- } else if is_base {
- InterfaceKind::Base
- } else {
- InterfaceKind::None
- };
- let mut found = false;
- for existing in result.iter_mut() {
- if existing.ty == child.ty {
- found = true;
- if child.kind == InterfaceKind::Default {
- existing.kind = child.kind
- }
- }
- }
- if !found {
- walk(reader, result, &child.ty, is_base);
- result.push(child);
- }
- }
- }
- }
- let mut result = Vec::new();
- walk(self, &mut result, ty, false);
- if let Type::TypeDef((row, _)) = ty {
- if self.type_def_kind(*row) == TypeKind::Class {
- for base in self.type_def_bases(*row) {
- walk(self, &mut result, &Type::TypeDef((base, Vec::new())), true);
- }
- for attribute in self.type_def_attributes(*row) {
- match self.attribute_name(attribute) {
- "StaticAttribute" | "ActivatableAttribute" => {
- for (_, arg) in self.attribute_args(attribute) {
- if let Value::TypeDef(row) = arg {
- result.push(Interface { ty: Type::TypeDef((row, Vec::new())), kind: InterfaceKind::Static });
- break;
- }
- }
- }
- _ => {}
- }
- }
- }
- }
- result.sort_by(|a, b| self.type_name(&a.ty).cmp(self.type_name(&b.ty)));
- result
- }
- 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)),
- _ => unimplemented!(),
- }
- }
- fn type_stdcall(&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((row, _)) => self.type_def_stdcall(*row),
- _ => 4,
- }
- }
- pub fn type_is_exclusive(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_exclusive(*row),
- _ => false,
- }
- }
- pub fn type_is_blittable(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_blittable(*row),
- Type::String | Type::BSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => false,
- Type::Win32Array((kind, _)) => self.type_is_blittable(kind),
- Type::WinrtArray(kind) => self.type_is_blittable(kind),
- _ => true,
- }
- }
- pub fn type_is_copyable(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_copyable(*row),
- Type::String | Type::BSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => false,
- Type::Win32Array((kind, _)) => self.type_is_copyable(kind),
- Type::WinrtArray(kind) => self.type_is_copyable(kind),
- _ => true,
- }
- }
- pub fn type_has_explicit_layout(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_has_explicit_layout(*row),
- Type::Win32Array((ty, _)) => self.type_has_explicit_layout(ty),
- _ => false,
- }
- }
- pub fn type_has_packing(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_has_packing(*row),
- Type::Win32Array((ty, _)) => self.type_has_packing(ty),
- _ => false,
- }
- }
- pub fn type_has_callback(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_has_callback(*row),
- Type::Win32Array((ty, _)) => self.type_has_callback(ty),
- _ => false,
- }
- }
- 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);
-
- for (known_name, kind) in CORE_TYPES {
- if full_name == known_name {
- return kind;
- }
- }
-
- 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(ty) = self.get(full_name).next() {
- Type::TypeDef((ty, Vec::new()))
- } else {
- panic!("Type not found: {}", full_name);
- }
- }
- fn type_from_blob(&self, blob: &mut Blob, enclosing: Option<TypeDef>, generics: &[Type]) -> Option<Type> {
- let is_winrt_const_ref = blob.read_modifiers().iter().any(|def| self.type_def_or_ref(*def) == TypeName::IsConst);
- let is_winrt_array_ref = blob.read_expected(0x10);
- if blob.read_expected(0x01) {
- return None;
- }
-
- let is_winrt_array = blob.read_expected(0x1D);
-
- let mut pointers = 0;
-
- while blob.read_expected(0x0f) {
- pointers += 1;
- }
-
- let mut kind = self.type_from_blob_impl(blob, enclosing, generics);
-
- if pointers > 0 {
- kind = Type::MutPtr((Box::new(kind), pointers));
- }
-
- Some(if is_winrt_array {
- if is_winrt_array_ref {
- Type::WinrtArrayRef(Box::new(kind))
- } else {
- Type::WinrtArray(Box::new(kind))
- }
- } else if is_winrt_const_ref {
- Type::WinrtConstRef(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 {
- 0x11 | 0x12 => self.type_from_ref(TypeDefOrRef::decode(blob.file, blob.read_usize()), enclosing, generics),
- 0x13 => generics.get(blob.read_usize()).unwrap_or(&Type::Void).clone(),
- 0x14 => {
- let kind = self.type_from_blob(blob, enclosing, generics).unwrap();
- let _rank = blob.read_usize();
- let _bounds_count = blob.read_usize();
- let bounds = blob.read_usize();
- Type::Win32Array((Box::new(kind), bounds))
- }
- 0x15 => {
- blob.read_usize();
-
- let def = self.get(self.type_def_or_ref(TypeDefOrRef::decode(blob.file, blob.read_usize()))).next().expect("Type not found");
- 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))
- }
- _ => unimplemented!(),
- }
- }
- pub fn type_name(&self, ty: &Type) -> &str {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_name(*row),
- _ => "",
- }
- }
- pub fn type_signature(&self, ty: &Type) -> String {
- match ty {
- Type::Bool => "b1".to_string(),
- Type::Char => "c2".to_string(),
- Type::I8 => "i1".to_string(),
- Type::U8 => "u1".to_string(),
- Type::I16 => "i2".to_string(),
- Type::U16 => "u2".to_string(),
- Type::I32 => "i4".to_string(),
- Type::U32 => "u4".to_string(),
- Type::I64 => "i8".to_string(),
- Type::U64 => "u8".to_string(),
- Type::F32 => "f4".to_string(),
- Type::F64 => "f8".to_string(),
- Type::String => "string".to_string(),
- Type::IInspectable => "cinterface(IInspectable)".to_string(),
- Type::GUID => "g16".to_string(),
- Type::HRESULT => "struct(Windows.Foundation.HResult;i4)".to_string(),
- Type::TypeDef((row, generics)) => self.type_def_signature(*row, generics),
- _ => unimplemented!(),
- }
- }
- pub fn type_is_nullable(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_nullable(*row),
- Type::IInspectable | Type::IUnknown => true,
- _ => false,
- }
- }
- fn type_is_borrowed(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_borrowed(*row),
- Type::BSTR | Type::PCSTR | Type::PCWSTR | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => true,
- _ => false,
- }
- }
- pub fn type_is_non_exclusive_winrt_interface(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => {
- let flags = self.type_def_flags(*row);
- if !flags.contains(TypeAttributes::WINRT) {
- false
- } else {
- match self.type_def_kind(*row) {
- TypeKind::Interface => !self.type_def_is_exclusive(*row),
- TypeKind::Class => self.type_def_is_composable(*row),
- _ => false,
- }
- }
- }
- _ => false,
- }
- }
- pub fn type_is_trivially_convertible(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_trivially_convertible(*row),
- Type::PCSTR | Type::PCWSTR => true,
- _ => false,
- }
- }
- pub fn type_is_callback(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_callback(*row),
- _ => false,
- }
- }
- pub fn type_is_primitive(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_primitive(*row),
- Type::Bool | Type::Char | Type::I8 | Type::U8 | Type::I16 | Type::U16 | Type::I32 | Type::U32 | Type::I64 | Type::U64 | Type::F32 | Type::F64 | Type::ISize | Type::USize | Type::HRESULT | Type::ConstPtr(_) | Type::MutPtr(_) => true,
- _ => false,
- }
- }
- pub fn type_is_struct(&self, ty: &Type) -> bool {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_is_struct(*row),
- Type::GUID => true,
- _ => false,
- }
- }
- pub fn type_underlying_type(&self, ty: &Type) -> Type {
- match ty {
- Type::TypeDef((row, _)) => self.type_def_underlying_type(*row),
- Type::HRESULT => Type::I32,
- _ => ty.clone(),
- }
- }
- pub fn type_has_replacement(&self, ty: &Type) -> bool {
- match ty {
- Type::HRESULT | Type::PCSTR | Type::PCWSTR => true,
- Type::TypeDef((row, _)) => self.type_def_is_handle(*row),
- _ => false,
- }
- }
-}
-
-pub const REMAP_TYPES: [(TypeName, TypeName); 2] = [(TypeName::D2D_MATRIX_3X2_F, TypeName::Matrix3x2), (TypeName::D3DMATRIX, TypeName::Matrix4x4)];
-
-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/row.rs b/vendor/windows-metadata/src/reader/row.rs
deleted file mode 100644
index 727edb201..000000000
--- a/vendor/windows-metadata/src/reader/row.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
-pub struct Row {
- pub row: u32,
- pub table: u16,
- pub file: u16,
-}
-
-impl Row {
- pub fn new(row: usize, table: usize, file: usize) -> Self {
- Self { row: row as _, table: table as _, file: file as _ }
- }
- pub fn next(&self) -> Self {
- Self { row: self.row + 1, table: self.table, file: self.file }
- }
-}
diff --git a/vendor/windows-metadata/src/reader/tree.rs b/vendor/windows-metadata/src/reader/tree.rs
deleted file mode 100644
index 3d576ea41..000000000
--- a/vendor/windows-metadata/src/reader/tree.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use super::*;
-
-#[derive(Debug)]
-pub struct Tree<'a> {
- pub namespace: &'a str,
- pub nested: BTreeMap<&'a str, Tree<'a>>,
-}
-
-impl<'a> Tree<'a> {
- pub(crate) fn from_namespace(namespace: &'a str) -> Self {
- Self { namespace, nested: BTreeMap::new() }
- }
- pub(crate) fn insert_namespace(&mut self, namespace: &'a str, pos: usize) -> &mut Self {
- if let Some(next) = namespace[pos..].find('.') {
- let next = pos + next;
- self.nested.entry(&namespace[pos..next]).or_insert_with(|| Self::from_namespace(&namespace[..next])).insert_namespace(namespace, next + 1)
- } else {
- self.nested.entry(&namespace[pos..]).or_insert_with(|| Self::from_namespace(namespace))
- }
- }
- pub fn flatten(&self) -> Vec<&Self> {
- std::iter::once(self).chain(self.nested.values().flat_map(|tree| tree.flatten())).collect()
- }
- pub fn seek(mut self, namespace: &'a str) -> Option<Self> {
- if let Some(next) = namespace.find('.') {
- self.nested.remove(&namespace[..next]).and_then(|tree| tree.seek(&namespace[next + 1..]))
- } else {
- self.nested.remove(namespace)
- }
- }
-}
diff --git a/vendor/windows-metadata/src/reader/type.rs b/vendor/windows-metadata/src/reader/type.rs
deleted file mode 100644
index 222f90150..000000000
--- a/vendor/windows-metadata/src/reader/type.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-use super::*;
-
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub enum Type {
- Void,
- Bool,
- Char,
- I8,
- U8,
- I16,
- U16,
- I32,
- U32,
- I64,
- U64,
- F32,
- F64,
- ISize,
- USize,
- String,
- GUID,
- IUnknown,
- IInspectable,
- HRESULT,
- PSTR,
- PWSTR,
- PCSTR,
- PCWSTR,
- BSTR,
- TypeName,
- GenericParam(GenericParam),
- TypeDef((TypeDef, Vec<Self>)),
- MutPtr((Box<Self>, usize)),
- ConstPtr((Box<Self>, usize)),
- Win32Array((Box<Self>, usize)),
- WinrtArray(Box<Self>),
- WinrtArrayRef(Box<Self>),
- WinrtConstRef(Box<Self>),
-}
-
-impl Type {
- /// Creates a `Type` object from an `ELEMENT_TYPE` (see ECMA-335) type constant, typically
- /// used to indicate the type of a constant or primitive type signature.
- pub fn from_code(code: usize) -> Option<Self> {
- match code {
- 0x01 => Some(Self::Void),
- 0x02 => Some(Self::Bool),
- 0x03 => Some(Self::Char),
- 0x04 => Some(Self::I8),
- 0x05 => Some(Self::U8),
- 0x06 => Some(Self::I16),
- 0x07 => Some(Self::U16),
- 0x08 => Some(Self::I32),
- 0x09 => Some(Self::U32),
- 0x0a => Some(Self::I64),
- 0x0b => Some(Self::U64),
- 0x0c => Some(Self::F32),
- 0x0d => Some(Self::F64),
- 0x18 => Some(Self::ISize),
- 0x19 => Some(Self::USize),
- 0x0e => Some(Self::String),
- 0x1c => Some(Self::IInspectable),
- _ => None,
- }
- }
-
- /// Converts the `Type` to an equivalent `const` variant if appropriate.
- pub fn to_const_type(self) -> Self {
- match self {
- Self::MutPtr((kind, pointers)) => Self::MutPtr((Box::new(kind.to_const_type()), pointers)),
- Self::ConstPtr((kind, pointers)) => Self::ConstPtr((Box::new(kind.to_const_type()), pointers)),
- Self::PSTR => Self::PCSTR,
- Self::PWSTR => Self::PCWSTR,
- _ => self,
- }
- }
-
- /// Converts a mutable pointer type, if appropriate, to a const pointer type.
- pub fn to_const_ptr(self) -> Self {
- match self {
- Self::MutPtr((kind, pointers)) => Self::ConstPtr((kind, pointers)),
- _ => self,
- }
- }
-
- /// Removes one level of indirection, typically used when transforming a logical return or array parameter
- /// from its underlying type signature.
- pub fn deref(&self) -> Self {
- match self {
- Self::ConstPtr((kind, 1)) | Self::MutPtr((kind, 1)) => {
- if **kind == Self::Void {
- Self::U8
- } else {
- *kind.clone()
- }
- }
- Self::ConstPtr((kind, pointers)) => Self::ConstPtr((kind.clone(), pointers - 1)),
- Self::MutPtr((kind, pointers)) => Self::MutPtr((kind.clone(), pointers - 1)),
- Self::PSTR | Self::PCSTR => Self::U8,
- Self::PWSTR | Self::PCWSTR => Self::U16,
- _ => panic!("`deref` can only be called on pointer types"),
- }
- }
-
- /// Returns `true` if the `Type` represents a WinRT array.
- pub fn is_winrt_array(&self) -> bool {
- matches!(self, Type::WinrtArray(_))
- }
-
- /// Returns `true` if the `Type` represents a mutable WinRT array reference.
- pub fn is_winrt_array_ref(&self) -> bool {
- matches!(self, Type::WinrtArrayRef(_))
- }
-
- /// Returns `true` if the `Type` represents an immutable WinRT array reference.
- pub fn is_winrt_const_ref(&self) -> bool {
- matches!(self, Type::WinrtConstRef(_))
- }
-
- /// Returns `true` if the `Type` is a generic parameter.
- pub fn is_generic(&self) -> bool {
- matches!(self, Type::GenericParam(_))
- }
-
- /// Returns `true` if the `Type` is a pointer.
- pub fn is_pointer(&self) -> bool {
- matches!(self, Type::ConstPtr(_) | Type::MutPtr(_))
- }
-
- /// Returns `true` if the `Type` is unsigned.
- pub fn is_unsigned(&self) -> bool {
- matches!(self, Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::USize)
- }
-
- /// Returns `true` if the `Type` is incomplete.
- pub fn is_void(&self) -> bool {
- match self {
- Type::ConstPtr((kind, _)) | Type::MutPtr((kind, _)) => kind.is_void(),
- Type::Void => true,
- _ => false,
- }
- }
-
- /// Returns `true` if the `Type` has a byte-sized address.
- pub fn is_byte_size(&self) -> bool {
- match self {
- Type::ConstPtr((kind, _)) | Type::MutPtr((kind, _)) => kind.is_byte_size(),
- Type::I8 | Type::U8 | Type::PSTR | Type::PCSTR => true,
- _ => false,
- }
- }
-}
diff --git a/vendor/windows-metadata/src/row.rs b/vendor/windows-metadata/src/row.rs
new file mode 100644
index 000000000..4e0c30593
--- /dev/null
+++ b/vendor/windows-metadata/src/row.rs
@@ -0,0 +1,91 @@
+#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
+pub struct Row {
+ pub row: usize,
+ pub file: usize,
+}
+
+impl Row {
+ pub fn new(row: usize, file: usize) -> Self {
+ Self { row, file }
+ }
+
+ fn next(&self) -> Self {
+ Self { row: self.row + 1, file: self.file }
+ }
+}
+
+pub trait AsRow: Copy {
+ const TABLE: usize;
+ fn to_row(&self) -> Row;
+ fn from_row(row: Row) -> Self;
+
+ fn file(&self) -> usize {
+ self.to_row().file
+ }
+
+ fn index(&self) -> usize {
+ self.to_row().row
+ }
+
+ fn next(&self) -> Self {
+ Self::from_row(self.to_row().next())
+ }
+}
+
+pub struct RowIterator<R: AsRow> {
+ file: usize,
+ 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 {
+ Self { file, rows, phantom: std::marker::PhantomData }
+ }
+}
+
+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)))
+ }
+}
+
+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)
+ }
+ }
+ )*
+};
+}
+
+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)
+}
diff --git a/vendor/windows-metadata/src/type.rs b/vendor/windows-metadata/src/type.rs
new file mode 100644
index 000000000..b62faff78
--- /dev/null
+++ b/vendor/windows-metadata/src/type.rs
@@ -0,0 +1,179 @@
+use super::*;
+
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
+pub enum Type {
+ // Primitives in ECMA-335
+ Void,
+ Bool,
+ Char,
+ I8,
+ U8,
+ I16,
+ U16,
+ I32,
+ U32,
+ I64,
+ U64,
+ F32,
+ F64,
+ ISize,
+ USize,
+
+ // System types
+ 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,
+
+ // 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.
+ GenericParam(GenericParam),
+ TypeDef(TypeDef, Vec<Self>),
+
+ // Qualified types
+ MutPtr(Box<Self>, usize),
+ ConstPtr(Box<Self>, usize),
+ Win32Array(Box<Self>, usize),
+ WinrtArray(Box<Self>),
+ WinrtArrayRef(Box<Self>),
+ ConstRef(Box<Self>),
+
+ // TODO: temporary hack to accommodate Win32 metadata
+ PrimitiveOrEnum(Box<Self>, Box<Self>),
+
+ // TODO: these should not be "special" and just point to regular metadata types in Win32.Foundation
+ HRESULT, // TODO: Win32 should use Windows.Foundation.HResult when referring to HRESULT
+ IUnknown, // TODO: should be defined in Windows.Win32.Foundation.IUnknown
+ PSTR,
+ PWSTR,
+ PCSTR,
+ PCWSTR,
+ BSTR,
+}
+
+impl Type {
+ /// Creates a `Type` object from an `ELEMENT_TYPE` (see ECMA-335) type constant, typically
+ /// used to indicate the type of a constant or primitive type signature.
+ pub fn from_code(code: usize) -> Option<Self> {
+ match code as u8 {
+ ELEMENT_TYPE_VOID => Some(Self::Void),
+ ELEMENT_TYPE_BOOLEAN => Some(Self::Bool),
+ ELEMENT_TYPE_CHAR => Some(Self::Char),
+ ELEMENT_TYPE_I1 => Some(Self::I8),
+ ELEMENT_TYPE_U1 => Some(Self::U8),
+ ELEMENT_TYPE_I2 => Some(Self::I16),
+ ELEMENT_TYPE_U2 => Some(Self::U16),
+ ELEMENT_TYPE_I4 => Some(Self::I32),
+ ELEMENT_TYPE_U4 => Some(Self::U32),
+ ELEMENT_TYPE_I8 => Some(Self::I64),
+ ELEMENT_TYPE_U8 => Some(Self::U64),
+ ELEMENT_TYPE_R4 => Some(Self::F32),
+ ELEMENT_TYPE_R8 => Some(Self::F64),
+ ELEMENT_TYPE_I => Some(Self::ISize),
+ ELEMENT_TYPE_U => Some(Self::USize),
+ ELEMENT_TYPE_STRING => Some(Self::String),
+ ELEMENT_TYPE_OBJECT => Some(Self::IInspectable),
+ _ => None,
+ }
+ }
+
+ /// Converts the `Type` to an equivalent `const` variant if appropriate.
+ pub fn to_const_type(self) -> Self {
+ match self {
+ Self::MutPtr(kind, pointers) => Self::MutPtr(Box::new(kind.to_const_type()), pointers),
+ Self::ConstPtr(kind, pointers) => Self::ConstPtr(Box::new(kind.to_const_type()), pointers),
+ Self::PSTR => Self::PCSTR,
+ Self::PWSTR => Self::PCWSTR,
+ _ => self,
+ }
+ }
+
+ pub fn to_underlying_type(&self) -> Self {
+ match self {
+ Type::MutPtr(ty, _) => *ty.clone(),
+ Type::ConstPtr(ty, _) => *ty.clone(),
+ Type::Win32Array(ty, _) => *ty.clone(),
+ Type::WinrtArray(ty) => *ty.clone(),
+ Type::WinrtArrayRef(ty) => *ty.clone(),
+ Type::ConstRef(ty) => *ty.clone(),
+ _ => self.clone(),
+ }
+ }
+
+ /// Converts a mutable pointer type, if appropriate, to a const pointer type.
+ pub fn to_const_ptr(self) -> Self {
+ match self {
+ Self::MutPtr(kind, pointers) => Self::ConstPtr(kind, pointers),
+ _ => self,
+ }
+ }
+
+ /// Removes one level of indirection, typically used when transforming a logical return or array parameter
+ /// from its underlying type signature.
+ pub fn deref(&self) -> Self {
+ match self {
+ Self::ConstPtr(kind, 1) | Self::MutPtr(kind, 1) => {
+ if **kind == Self::Void {
+ Self::U8
+ } else {
+ *kind.clone()
+ }
+ }
+ Self::ConstPtr(kind, pointers) => Self::ConstPtr(kind.clone(), pointers - 1),
+ Self::MutPtr(kind, pointers) => Self::MutPtr(kind.clone(), pointers - 1),
+ Self::PSTR | Self::PCSTR => Self::U8,
+ Self::PWSTR | Self::PCWSTR => Self::U16,
+ _ => panic!("`deref` can only be called on pointer types"),
+ }
+ }
+
+ /// Returns `true` if the `Type` represents a WinRT array.
+ pub fn is_winrt_array(&self) -> bool {
+ matches!(self, Type::WinrtArray(_))
+ }
+
+ /// Returns `true` if the `Type` represents a mutable WinRT array reference.
+ pub fn is_winrt_array_ref(&self) -> bool {
+ matches!(self, Type::WinrtArrayRef(_))
+ }
+
+ /// Returns `true` if the `Type` represents an immutable WinRT array reference.
+ pub fn is_const_ref(&self) -> bool {
+ matches!(self, Type::ConstRef(_))
+ }
+
+ /// Returns `true` if the `Type` is a generic parameter.
+ pub fn is_generic(&self) -> bool {
+ matches!(self, Type::GenericParam(_))
+ }
+
+ /// Returns `true` if the `Type` is a pointer.
+ pub fn is_pointer(&self) -> bool {
+ matches!(self, Type::ConstPtr(_, _) | Type::MutPtr(_, _))
+ }
+
+ /// Returns `true` if the `Type` is unsigned.
+ pub fn is_unsigned(&self) -> bool {
+ matches!(self, Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::USize)
+ }
+
+ /// Returns `true` if the `Type` is incomplete.
+ pub fn is_void(&self) -> bool {
+ match self {
+ Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_void(),
+ Type::Void => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the `Type` has a byte-sized address.
+ pub fn is_byte_size(&self) -> bool {
+ match self {
+ Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_byte_size(),
+ Type::I8 | Type::U8 | Type::PSTR | Type::PCSTR => true,
+ _ => false,
+ }
+ }
+}
diff --git a/vendor/windows-metadata/src/reader/type_name.rs b/vendor/windows-metadata/src/type_name.rs
index 2e7b40808..750d58c3e 100644
--- a/vendor/windows-metadata/src/reader/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,
}
-#[allow(non_upper_case_globals)]
impl<'a> TypeName<'a> {
- pub const None: Self = Self::from_const("", "");
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");
@@ -37,6 +37,8 @@ impl<'a> TypeName<'a> {
pub const HANDLE: Self = Self::from_const("Windows.Win32.Foundation", "HANDLE");
pub const HRESULT: Self = Self::from_const("Windows.Win32.Foundation", "HRESULT");
pub const CHAR: Self = Self::from_const("Windows.Win32.Foundation", "CHAR");
+ pub const BOOL: Self = Self::from_const("Windows.Win32.Foundation", "BOOL");
+ pub const WIN32_ERROR: Self = Self::from_const("Windows.Win32.Foundation", "WIN32_ERROR");
pub const D2D_MATRIX_3X2_F: Self = Self::from_const("Windows.Win32.Graphics.Direct2D.Common", "D2D_MATRIX_3X2_F");
pub const D3DMATRIX: Self = Self::from_const("Windows.Win32.Graphics.Direct3D", "D3DMATRIX");
@@ -51,7 +53,7 @@ impl<'a> TypeName<'a> {
}
pub fn new(namespace: &'a str, name: &'a str) -> Self {
- Self { namespace, name: trim_tick(name) }
+ Self { namespace, name: crate::trim_tick(name) }
}
pub fn parse(full_name: &'a str) -> Self {
@@ -65,11 +67,3 @@ impl<'a> std::fmt::Display for TypeName<'a> {
write!(fmt, "{}.{}", self.namespace, self.name)
}
}
-
-pub 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/writer/imp/blobs.rs b/vendor/windows-metadata/src/writer/imp/blobs.rs
deleted file mode 100644
index 08bad113d..000000000
--- a/vendor/windows-metadata/src/writer/imp/blobs.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use super::*;
-
-#[derive(Default)]
-pub struct Blobs {
- // Blobs don't need to be sorted. A map is used to collapse duplicates. A `BTreeMap` in particular is used to help with reproducible builds.
- map: BTreeMap<Vec<u8>, u32>,
- stream: Vec<u8>,
-}
-
-pub struct StagedBlobs(Blobs);
-
-impl Blobs {
- pub fn insert(&mut self, value: Vec<u8>) {
- if !value.is_empty() {
- self.map.entry(value).or_default();
- }
- }
-
- pub fn stage(mut self) -> StagedBlobs {
- self.stream = vec![0];
-
- for (value, index) in self.map.iter_mut() {
- *index = self.stream.len() as _;
-
- match value.len() {
- 0..=0x7F => self.stream.push(value.len() as _),
- 0x80..=0x3FFF => {
- self.stream.push((0x80 | value.len() >> 8) as _);
- self.stream.push((0xFF & value.len()) as _);
- }
- _ => {
- self.stream.push((0xC0 | value.len() >> 24) as _);
- self.stream.push((0xFF & value.len() >> 16) as _);
- self.stream.push((0xFF & value.len() >> 8) as _);
- self.stream.push((0xFF & value.len()) as _);
- }
- }
-
- self.stream.extend_from_slice(value);
- }
-
- self.stream.resize(round(self.stream.len(), 4), 0);
- StagedBlobs(self)
- }
-}
-
-impl StagedBlobs {
- pub fn stream(self) -> Vec<u8> {
- self.0.stream
- }
-
- #[track_caller]
- pub fn index(&self, value: &[u8]) -> u32 {
- if value.is_empty() {
- 0
- } else {
- self.0.map[value]
- }
- }
-}
diff --git a/vendor/windows-metadata/src/writer/imp/codes.rs b/vendor/windows-metadata/src/writer/imp/codes.rs
deleted file mode 100644
index 3c1b60048..000000000
--- a/vendor/windows-metadata/src/writer/imp/codes.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-/// A `ResolutionScope` is an index into a certain table indicating the scope in which a TypeRef can be resolved.
-#[derive(Default, Clone)]
-pub enum ResolutionScope {
- #[default]
- None,
- Module(u32),
- ModuleRef(u32),
- AssemblyRef(u32),
- TypeRef(u32),
-}
-
-impl ResolutionScope {
- pub fn encode(&self) -> u32 {
- match self {
- Self::Module(row) => (row + 1) << 2,
- Self::ModuleRef(row) => ((row + 1) << 2) + 1,
- Self::AssemblyRef(row) => ((row + 1) << 2) + 2,
- Self::TypeRef(row) => ((row + 1) << 2) + 3,
- _ => 0,
- }
- }
-}
-
-/// A `TypeDefOrRef` is an index into a certain table used to locate a type definition.
-#[derive(Default, Clone)]
-pub enum TypeDefOrRef {
- #[default]
- None,
- TypeDef(u32),
- TypeRef(u32),
- TypeSpec(u32),
-}
-
-impl TypeDefOrRef {
- pub fn encode(&self) -> u32 {
- match self {
- Self::TypeDef(row) => (row + 1) << 2,
- Self::TypeRef(row) => ((row + 1) << 2) + 1,
- Self::TypeSpec(row) => ((row + 1) << 2) + 2,
- _ => 0,
- }
- }
-}
-
-/// A `HasConstant` is an index into a certain table used to identify the parent of a row in the `Constant` table.
-#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub enum HasConstant {
- #[default]
- None,
- Field(u32),
- Param(u32),
- Property(u32),
-}
-
-impl HasConstant {
- pub fn encode(&self) -> u32 {
- match self {
- Self::Field(row) => (row + 1) << 2,
- Self::Param(row) => ((row + 1) << 2) + 1,
- Self::Property(row) => ((row + 1) << 2) + 2,
- _ => 0,
- }
- }
-}
-
-#[derive(Default, Clone)]
-pub enum HasCustomAttribute {
- #[default]
- None,
-}
-
-#[derive(Default, Clone)]
-pub enum CustomAttributeType {
- #[default]
- None,
-}
-
-#[derive(Default, Clone)]
-pub enum TypeOrMethodDef {
- #[default]
- None,
-}
-
-#[derive(Default, Clone)]
-pub enum MemberForwarded {
- #[default]
- None,
-}
-
-#[derive(Default, Clone)]
-pub enum MemberRefParent {
- #[default]
- None,
-}
diff --git a/vendor/windows-metadata/src/writer/imp/definitions.rs b/vendor/windows-metadata/src/writer/imp/definitions.rs
deleted file mode 100644
index 476e3ed52..000000000
--- a/vendor/windows-metadata/src/writer/imp/definitions.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use super::*;
-
-#[derive(Default)]
-pub struct Definitions<'a> {
- map: BTreeMap<(&'a str, &'a str), Definition<'a>>,
-}
-
-pub struct Definition<'a> {
- pub item: &'a Item,
- pub index: u32,
- pub value_type: bool,
-}
-
-pub struct StagedDefinitions<'a>(Definitions<'a>);
-
-impl<'a> Definitions<'a> {
- pub fn insert(&mut self, item: &'a Item) {
- if self.map.insert(item_type_name(item), Definition { item, index: 0, value_type: item_value_type(item) }).is_some() {
- panic!("Duplicate type found");
- }
- }
-
- pub fn stage(mut self) -> StagedDefinitions<'a> {
- for (index, value) in self.map.values_mut().enumerate() {
- value.index = index as _;
- }
- StagedDefinitions(self)
- }
-}
-
-impl<'a> StagedDefinitions<'a> {
- pub fn get(&self, namespace: &'a str, name: &'a str) -> Option<&'a Definition> {
- self.0.map.get(&(namespace, name))
- }
-
- pub fn items(&self) -> impl Iterator<Item = &Item> {
- self.0.map.values().map(|value| value.item)
- }
-
- pub fn iter(&self) -> impl Iterator<Item = (u32, &Item)> {
- self.0.map.values().map(|value| (value.index, value.item))
- }
-}
diff --git a/vendor/windows-metadata/src/writer/imp/file.rs b/vendor/windows-metadata/src/writer/imp/file.rs
deleted file mode 100644
index 2f25f942b..000000000
--- a/vendor/windows-metadata/src/writer/imp/file.rs
+++ /dev/null
@@ -1,138 +0,0 @@
-use super::*;
-use std::mem::*;
-
-pub fn write(tables: Tables, strings: StagedStrings, blobs: StagedBlobs) -> Vec<u8> {
- unsafe {
- let mut tables = tables.stream();
- let mut strings = strings.stream();
- let mut blobs = blobs.stream();
- let mut guids = vec![0; 16]; // zero guid
- let size_of_streams = tables.len() + guids.len() + strings.len() + blobs.len();
-
- let mut dos: IMAGE_DOS_HEADER = zeroed();
- dos.e_magic = IMAGE_DOS_SIGNATURE as _;
- dos.e_lfarlc = 64;
- dos.e_lfanew = size_of::<IMAGE_DOS_HEADER>() as _;
-
- let mut file: IMAGE_FILE_HEADER = zeroed();
- file.Machine = IMAGE_FILE_MACHINE_I386;
- file.NumberOfSections = 1;
- file.SizeOfOptionalHeader = size_of::<IMAGE_OPTIONAL_HEADER32>() as _;
- file.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE;
-
- let mut optional: IMAGE_OPTIONAL_HEADER32 = zeroed();
- optional.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
- optional.MajorLinkerVersion = 11;
- optional.SizeOfInitializedData = 1024;
- optional.ImageBase = 0x400000;
- optional.SectionAlignment = SECTION_ALIGNMENT;
- optional.FileAlignment = 512;
- optional.MajorOperatingSystemVersion = 6;
- optional.MinorOperatingSystemVersion = 2;
- optional.MajorSubsystemVersion = 6;
- optional.MinorSubsystemVersion = 2;
- optional.SizeOfHeaders = 512;
- optional.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
- optional.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_NO_SEH | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
- optional.SizeOfStackReserve = 0x100000;
- optional.SizeOfHeapReserve = 4096;
- optional.LoaderFlags = 0x100000;
- optional.NumberOfRvaAndSizes = 16;
-
- let mut section: IMAGE_SECTION_HEADER = zeroed();
- section.Name = *b".text\0\0\0";
- section.Characteristics = 0x4000_0020;
- section.VirtualAddress = SECTION_ALIGNMENT;
-
- let mut clr: IMAGE_COR20_HEADER = zeroed();
- clr.cb = size_of::<IMAGE_COR20_HEADER>() as _;
- clr.MajorRuntimeVersion = 2;
- clr.MinorRuntimeVersion = 5;
- clr.Flags = 1;
-
- let metadata = METADATA_HEADER {
- signature: METADATA_SIGNATURE,
- major_version: 1,
- minor_version: 1,
- length: 20,
- version: *b"WindowsRuntime\0\0\0\0\0\0",
- streams: 4,
- ..Default::default()
- };
-
- type TablesHeader = StreamHeader<4>;
- type StringsHeader = StreamHeader<12>;
- type GuidsHeader = StreamHeader<8>;
- type BlobsHeader = StreamHeader<8>;
-
- let size_of_stream_headers = size_of::<TablesHeader>() + size_of::<StringsHeader>() + size_of::<GuidsHeader>() + size_of::<BlobsHeader>();
- let size_of_image = optional.FileAlignment as usize + size_of::<IMAGE_COR20_HEADER>() + size_of::<METADATA_HEADER>() + size_of_stream_headers + size_of_streams;
-
- optional.SizeOfImage = round(size_of_image, optional.SectionAlignment as _) as _;
- section.Misc.VirtualSize = size_of_image as u32 - optional.FileAlignment;
- section.SizeOfRawData = round(section.Misc.VirtualSize as _, optional.FileAlignment as _) as _;
-
- optional.DataDirectory[14] = IMAGE_DATA_DIRECTORY { VirtualAddress: SECTION_ALIGNMENT, Size: size_of::<IMAGE_COR20_HEADER>() as _ };
- section.PointerToRawData = optional.FileAlignment;
- clr.MetaData.VirtualAddress = SECTION_ALIGNMENT + size_of::<IMAGE_COR20_HEADER>() as u32;
- clr.MetaData.Size = section.Misc.VirtualSize - size_of::<IMAGE_COR20_HEADER>() as u32;
-
- let mut buffer = Vec::<u8>::new();
-
- buffer.write_header(&dos);
- buffer.write_u32(IMAGE_NT_SIGNATURE);
- buffer.write_header(&file);
- buffer.write_header(&optional);
- buffer.write_header(&section);
- debug_assert!(buffer.len() < optional.FileAlignment as _);
- buffer.resize(optional.FileAlignment as _, 0);
- buffer.write_header(&clr);
- let metadata_offset = buffer.len();
- buffer.write_header(&metadata);
-
- let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers;
- let tables_header = TablesHeader::new(stream_offset as _, tables.len() as _, b"#~\0\0");
- let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as _, b"#Strings\0\0\0\0");
- let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as _, b"#GUID\0\0\0");
- let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as _, b"#Blob\0\0\0");
-
- buffer.write_header(&tables_header);
- buffer.write_header(&strings_header);
- buffer.write_header(&guids_header);
- buffer.write_header(&blobs_header);
-
- buffer.append(&mut tables);
- buffer.append(&mut strings);
- buffer.append(&mut guids);
- buffer.append(&mut blobs);
-
- assert_eq!(clr.MetaData.Size as usize, buffer.len() - metadata_offset);
- assert_eq!(size_of_image, buffer.len());
-
- buffer
- }
-}
-
-const SECTION_ALIGNMENT: u32 = 4096;
-
-#[repr(C)]
-struct StreamHeader<const LEN: usize> {
- offset: u32,
- size: u32,
- name: [u8; LEN],
-}
-
-impl<const LEN: usize> StreamHeader<LEN> {
- fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self {
- Self { offset, size, name: *name }
- }
- fn next_offset(&self) -> u32 {
- self.offset + self.size
- }
-}
-
-fn guid_stream() -> Vec<u8> {
- let mut buffer = Vec::new();
- buffer.resize(16, 0); // zero guid
- buffer
-}
diff --git a/vendor/windows-metadata/src/writer/imp/mod.rs b/vendor/windows-metadata/src/writer/imp/mod.rs
deleted file mode 100644
index adecde371..000000000
--- a/vendor/windows-metadata/src/writer/imp/mod.rs
+++ /dev/null
@@ -1,408 +0,0 @@
-mod blobs;
-mod codes;
-mod definitions;
-mod file;
-mod references;
-mod strings;
-mod tables;
-
-use super::*;
-use blobs::*;
-use codes::*;
-use definitions::*;
-use references::*;
-use strings::*;
-use tables::Tables;
-
-use std::collections::BTreeMap;
-
-pub fn round(size: usize, round: usize) -> usize {
- let round = round - 1;
- (size + round) & !round
-}
-
-pub fn write(name: &str, winrt: bool, definitions: &[Item], assemblies: &[&str]) -> Vec<u8> {
- // Index assemblies used to resolve references to existing winmd files.
- let assemblies: Vec<reader::File> = assemblies.iter().map(|file| reader::File::new(file).expect("Assemblies could not be loaded")).collect();
- let assemblies = &reader::Reader::new(&assemblies);
-
- // Build sorted list of definitions.
- let definitions = &{
- let mut index = Definitions::default();
- definitions.iter().for_each(|item| index.insert(item));
- index.stage()
- };
-
- // Build sorted list of references.
- let references = &{
- let mut index = References::default();
- for item in definitions.items() {
- match item {
- Item::Struct(ty) => ty.fields.iter().for_each(|field| type_reference(&field.ty, definitions, assemblies, &mut index)),
- Item::Interface(_ty) => {}
- _ => {}
- }
- }
- index.stage()
- };
-
- // Now that we have stable type indexes, build blobs and index strings.
- let (blobs, strings) = {
- let mut blobs = Blobs::default();
- let mut strings = Strings::default();
- strings.insert(name);
- strings.insert("<Module>");
- strings.insert("mscorlib");
- strings.insert("System");
- strings.insert("ValueType");
- strings.insert("Enum");
- strings.insert("value__");
-
- for item in definitions.items() {
- match item {
- Item::Struct(ty) => {
- strings.insert(&ty.namespace);
- strings.insert(&ty.name);
- ty.fields.iter().for_each(|field| {
- strings.insert(&field.name);
- blobs.insert(field_blob(&field.ty, definitions, references));
- });
- }
- Item::Enum(ty) => {
- strings.insert(&ty.namespace);
- strings.insert(&ty.name);
- let enum_type = Type::Named((ty.namespace.clone(), ty.name.clone()));
- blobs.insert(field_blob(&enum_type, definitions, references));
- blobs.insert(field_blob(&value_to_type(&ty.constants[0].value), definitions, references));
- ty.constants.iter().for_each(|constant| {
- strings.insert(&constant.name);
- blobs.insert(value_blob(&constant.value));
- });
- }
- Item::Interface(ty) => {
- strings.insert(&ty.namespace);
- strings.insert(&ty.name);
- ty.methods.iter().for_each(|method| {
- strings.insert(&method.name);
- blobs.insert(method_blob(method, definitions, references));
- method.params.iter().for_each(|param| {
- strings.insert(&param.name);
- });
- });
- }
- }
- }
-
- (blobs.stage(), strings.stage())
- };
-
- // Now that everything is indexed in various heaps, write out the table records.
- let tables = {
- let mut tables = Tables::default();
- tables.Module.push(tables::Module { Name: strings.index(name), Mvid: 1, ..Default::default() });
- tables.TypeDef.push(tables::TypeDef { TypeName: strings.index("<Module>"), ..Default::default() });
- let mscorlib = tables.AssemblyRef.push2(tables::AssemblyRef { MajorVersion: 4, Name: strings.index("mscorlib"), ..Default::default() });
- let value_type = tables.TypeRef.push2(tables::TypeRef { TypeName: strings.index("ValueType"), TypeNamespace: strings.index("System"), ResolutionScope: ResolutionScope::AssemblyRef(mscorlib).encode() });
- let enum_type = tables.TypeRef.push2(tables::TypeRef { TypeName: strings.index("Enum"), TypeNamespace: strings.index("System"), ResolutionScope: ResolutionScope::AssemblyRef(mscorlib).encode() });
-
- for (_index, item) in definitions.iter() {
- match item {
- Item::Struct(ty) => {
- let mut flags = TypeAttributes::PUBLIC | TypeAttributes::SEQUENTIAL_LAYOUT | TypeAttributes::SEALED;
- if winrt {
- flags |= TypeAttributes::WINRT;
- }
- tables.TypeDef.push(tables::TypeDef {
- Flags: flags.0,
- TypeName: strings.index(&ty.name),
- TypeNamespace: strings.index(&ty.namespace),
- Extends: TypeDefOrRef::TypeRef(value_type).encode(),
- FieldList: tables.Field.len() as _,
- MethodList: tables.MethodDef.len() as _,
- });
- for field in &ty.fields {
- let flags = FieldAttributes::PUBLIC;
- tables.Field.push(tables::Field { Flags: flags.0, Name: strings.index(&field.name), Signature: blobs.index(&field_blob(&field.ty, definitions, references)) });
- }
- }
- Item::Enum(ty) => {
- let mut flags = TypeAttributes::PUBLIC | TypeAttributes::SEALED;
- if winrt {
- flags |= TypeAttributes::WINRT;
- }
- tables.TypeDef.push(tables::TypeDef {
- Flags: flags.0,
- TypeName: strings.index(&ty.name),
- TypeNamespace: strings.index(&ty.namespace),
- Extends: TypeDefOrRef::TypeRef(enum_type).encode(),
- FieldList: tables.Field.len() as _,
- MethodList: tables.MethodDef.len() as _,
- });
- let enum_type = Type::Named((ty.namespace.clone(), ty.name.clone()));
- let flags = FieldAttributes::PRIVATE | FieldAttributes::SPECIAL | FieldAttributes::RUNTIME_SPECIAL;
- tables.Field.push2(tables::Field {
- Flags: flags.0,
- Name: strings.index("value__"),
- Signature: blobs.index(&field_blob(&value_to_type(&ty.constants[0].value), definitions, references)),
- });
- for constant in &ty.constants {
- let flags = FieldAttributes::PUBLIC | FieldAttributes::STATIC | FieldAttributes::LITERAL | FieldAttributes::HAS_DEFAULT;
- let field = tables.Field.push2(tables::Field { Flags: flags.0, Name: strings.index(&constant.name), Signature: blobs.index(&field_blob(&enum_type, definitions, references)) });
- tables.Constant.push(tables::Constant { Type: value_type_code(&constant.value), Parent: HasConstant::Field(field).encode(), Value: blobs.index(&value_blob(&constant.value)) });
- }
- }
- Item::Interface(ty) => {
- let mut flags = TypeAttributes::PUBLIC | TypeAttributes::INTERFACE | TypeAttributes::ABSTRACT;
- if winrt {
- flags |= TypeAttributes::WINRT;
- }
- tables.TypeDef.push(tables::TypeDef {
- Flags: flags.0,
- TypeName: strings.index(&ty.name),
- TypeNamespace: strings.index(&ty.namespace),
- Extends: 0,
- FieldList: tables.Field.len() as _,
- MethodList: tables.MethodDef.len() as _,
- });
- for method in &ty.methods {
- let flags = MethodAttributes::ABSTRACT | MethodAttributes::HIDE_BY_SIG | MethodAttributes::NEW_SLOT | MethodAttributes::PUBLIC | MethodAttributes::VIRTUAL;
- tables.MethodDef.push(tables::MethodDef {
- RVA: 0,
- ImplFlags: 0,
- Flags: flags.0,
- Name: strings.index(&method.name),
- Signature: blobs.index(&method_blob(method, definitions, references)),
- ParamList: tables.Param.len() as _,
- });
- for (sequence, param) in method.params.iter().enumerate() {
- tables.Param.push(tables::Param { Flags: param_flags_to_attributes(param.flags).0, Sequence: (sequence + 1) as _, Name: strings.index(&param.name) });
- }
- }
- }
- }
- }
-
- tables
- };
-
- // With all of the streams prepared, write out ECMA-335 file format.
- file::write(tables, strings, blobs)
-}
-
-fn type_reference<'a>(ty: &'a Type, definitions: &StagedDefinitions, assemblies: &reader::Reader, references: &mut References<'a>) {
- // TODO: More matches to come...
- #[allow(clippy::single_match)]
- match ty {
- Type::Named((namespace, name)) => {
- if definitions.get(namespace, name).is_none() {
- references.insert(namespace, name, assemblies);
- }
- }
- _ => {}
- }
-}
-
-fn param_flags_to_attributes(flags: ParamFlags) -> ParamAttributes {
- let mut attributes = ParamAttributes(0);
- if flags.contains(ParamFlags::INPUT) {
- attributes |= ParamAttributes::INPUT;
- }
- if flags.contains(ParamFlags::OUTPUT) {
- attributes |= ParamAttributes::OUTPUT;
- }
- if flags.contains(ParamFlags::OPTIONAL) {
- attributes |= ParamAttributes::OPTIONAL;
- }
- attributes
-}
-
-fn item_type_name(item: &Item) -> (&str, &str) {
- match item {
- Item::Struct(ty) => (ty.namespace.as_str(), ty.name.as_str()),
- Item::Enum(ty) => (ty.namespace.as_str(), ty.name.as_str()),
- Item::Interface(ty) => (ty.namespace.as_str(), ty.name.as_str()),
- }
-}
-
-fn item_value_type(item: &Item) -> bool {
- match item {
- Item::Struct(_) | Item::Enum(_) => true,
- Item::Interface(_) => false,
- }
-}
-
-fn method_blob(method: &Method, definitions: &StagedDefinitions, references: &StagedReferences) -> Vec<u8> {
- let mut blob = vec![0x20]; // HASTHIS
- u32_blob(method.params.len() as _, &mut blob);
- for param in &method.params {
- type_blob(&param.ty, &mut blob, definitions, references);
- }
- type_blob(&method.return_type, &mut blob, definitions, references);
- blob
-}
-
-fn field_blob(ty: &Type, definitions: &StagedDefinitions, references: &StagedReferences) -> Vec<u8> {
- let mut blob = vec![0x6];
- type_blob(ty, &mut blob, definitions, references);
- blob
-}
-
-fn value_blob(value: &Value) -> Vec<u8> {
- match value {
- Value::I8(value) => value.to_le_bytes().to_vec(),
- Value::U8(value) => value.to_le_bytes().to_vec(),
- Value::I16(value) => value.to_le_bytes().to_vec(),
- Value::U16(value) => value.to_le_bytes().to_vec(),
- Value::I32(value) => value.to_le_bytes().to_vec(),
- Value::U32(value) => value.to_le_bytes().to_vec(),
- Value::I64(value) => value.to_le_bytes().to_vec(),
- Value::U64(value) => value.to_le_bytes().to_vec(),
- _ => panic!("Unsupported value type"),
- }
-}
-
-fn value_to_type(value: &Value) -> Type {
- match value {
- Value::I8(_) => Type::I8,
- Value::U8(_) => Type::U8,
- Value::I16(_) => Type::I16,
- Value::U16(_) => Type::U16,
- Value::I32(_) => Type::I32,
- Value::U32(_) => Type::U32,
- Value::I64(_) => Type::I64,
- Value::U64(_) => Type::U64,
- _ => panic!("Unsupported value type"),
- }
-}
-
-fn value_type_code(value: &Value) -> u16 {
- match value {
- Value::I8(_) => 0x04,
- Value::U8(_) => 0x05,
- Value::I16(_) => 0x06,
- Value::U16(_) => 0x07,
- Value::I32(_) => 0x08,
- Value::U32(_) => 0x09,
- Value::I64(_) => 0x0a,
- Value::U64(_) => 0x0b,
- _ => panic!("Unsupported value type"),
- }
-}
-
-fn type_blob(ty: &Type, blob: &mut Vec<u8>, definitions: &StagedDefinitions, references: &StagedReferences) {
- match ty {
- Type::Void => blob.push(0x01),
- Type::Bool => blob.push(0x02),
- Type::Char => blob.push(0x03),
- Type::I8 => blob.push(0x04),
- Type::U8 => blob.push(0x05),
- Type::I16 => blob.push(0x06),
- Type::U16 => blob.push(0x07),
- Type::I32 => blob.push(0x08),
- Type::U32 => blob.push(0x09),
- Type::I64 => blob.push(0x0a),
- Type::U64 => blob.push(0x0b),
- Type::F32 => blob.push(0x0c),
- Type::F64 => blob.push(0x0d),
- Type::ISize => blob.push(0x18),
- Type::USize => blob.push(0x19),
- Type::String => blob.push(0x0e),
- //Type::IInspectable => blob.push(0x1c),
- Type::Named((namespace, name)) => {
- let (value_type, code) = type_name_encode(namespace, name, definitions, references);
- value_type_blob(value_type, blob);
- u32_blob(code, blob);
- }
- }
-}
-
-fn value_type_blob(value_type: bool, blob: &mut Vec<u8>) {
- if value_type {
- blob.push(0x11);
- } else {
- blob.push(0x12);
- }
-}
-
-fn u32_blob(value: u32, blob: &mut Vec<u8>) {
- if value < 0x80 {
- blob.push(value as _);
- } else if value < 0x4000 {
- blob.push((0x40 | (value & 0xFF00)) as _);
- blob.push((value | 0xFF) as _);
- } else {
- blob.push((0x60 | (value & 0xFF000000)) as _);
- blob.push((value | 0xFF0000) as _);
- blob.push((value | 0xFF00) as _);
- blob.push((value | 0xFF) as _);
- }
-}
-
-/// Returns the TypeDefOrRef-encoded value for the type name as well as whether the type is a value type, needed
-/// in some cases like when a TypeDefOrRef appears in a signature.
-fn type_name_encode(namespace: &str, name: &str, definitions: &StagedDefinitions, references: &StagedReferences) -> (bool, u32) {
- if let Some(definition) = definitions.get(namespace, name) {
- return (definition.value_type, TypeDefOrRef::TypeDef(definition.index + 1).encode());
- }
- let reference = references.get(namespace, name).expect("Type not found");
- (reference.value_type, TypeDefOrRef::TypeRef(reference.index + 1).encode())
-}
-
-pub trait Write {
- unsafe fn write_header<T: Sized>(&mut self, value: &T);
- fn write_u8(&mut self, value: u8);
- fn write_u16(&mut self, value: u16);
- fn write_u32(&mut self, value: u32);
- fn write_u64(&mut self, value: u64);
- fn write_code(&mut self, value: u32, size: usize);
- fn write_index(&mut self, index: u32, len: usize);
-}
-
-impl Write for Vec<u8> {
- unsafe fn write_header<T: Sized>(&mut self, value: &T) {
- self.extend_from_slice(std::slice::from_raw_parts(value as *const _ as _, std::mem::size_of::<T>()));
- }
-
- fn write_u8(&mut self, value: u8) {
- self.extend_from_slice(&value.to_le_bytes());
- }
-
- fn write_u16(&mut self, value: u16) {
- self.extend_from_slice(&value.to_le_bytes());
- }
-
- fn write_u32(&mut self, value: u32) {
- self.extend_from_slice(&value.to_le_bytes());
- }
-
- fn write_u64(&mut self, value: u64) {
- self.extend_from_slice(&value.to_le_bytes());
- }
-
- fn write_code(&mut self, value: u32, size: usize) {
- if size == 2 {
- self.write_u16(value as _);
- } else {
- self.write_u32(value);
- }
- }
-
- fn write_index(&mut self, index: u32, len: usize) {
- if len < (1 << 16) {
- self.write_u16(index as u16 + 1);
- } else {
- self.write_u32(index + 1);
- }
- }
-}
-
-trait Push2<T> {
- fn push2(&mut self, value: T) -> u32;
-}
-
-impl<T> Push2<T> for Vec<T> {
- fn push2(&mut self, value: T) -> u32 {
- self.push(value);
- (self.len() - 1) as _
- }
-}
diff --git a/vendor/windows-metadata/src/writer/imp/references.rs b/vendor/windows-metadata/src/writer/imp/references.rs
deleted file mode 100644
index b35a8a275..000000000
--- a/vendor/windows-metadata/src/writer/imp/references.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use super::*;
-
-#[derive(Default)]
-pub struct References<'a> {
- map: BTreeMap<(&'a str, &'a str), Reference>,
-}
-
-pub struct Reference {
- pub index: u32,
- pub value_type: bool,
-}
-
-pub struct StagedReferences<'a>(References<'a>);
-
-impl<'a> References<'a> {
- pub fn insert(&mut self, namespace: &'a str, name: &'a str, assemblies: &reader::Reader) {
- self.map.entry((namespace, name)).or_insert_with(|| {
- let type_def = assemblies.get(reader::TypeName::new(namespace, name)).next().expect("Type not found");
- let value_type = matches!(assemblies.type_def_kind(type_def), reader::TypeKind::Struct | reader::TypeKind::Enum);
- Reference { value_type, index: 0 }
- });
- }
-
- pub fn stage(mut self) -> StagedReferences<'a> {
- for (index, value) in self.map.values_mut().enumerate() {
- value.index = index as _;
- }
- StagedReferences(self)
- }
-}
-
-impl<'a> StagedReferences<'a> {
- pub fn get(&'a self, namespace: &'a str, name: &'a str) -> Option<&'a Reference> {
- self.0.map.get(&(namespace, name))
- }
-}
diff --git a/vendor/windows-metadata/src/writer/imp/strings.rs b/vendor/windows-metadata/src/writer/imp/strings.rs
deleted file mode 100644
index da20e8cde..000000000
--- a/vendor/windows-metadata/src/writer/imp/strings.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-use super::*;
-
-#[derive(Default)]
-pub struct Strings<'a> {
- // Strings don't need to be sorted. A map is used to collapse duplicates. A `BTreeMap` in particular is used to help with reproducible builds.
- map: BTreeMap<&'a str, u32>,
- stream: Vec<u8>,
-}
-
-pub struct StagedStrings<'a>(Strings<'a>);
-
-impl<'a> Strings<'a> {
- pub fn insert(&mut self, value: &'a str) {
- if !value.is_empty() {
- self.map.entry(value).or_default();
- }
- }
-
- pub fn stage(mut self) -> StagedStrings<'a> {
- self.stream = vec![0];
-
- for (value, index) in self.map.iter_mut() {
- *index = self.stream.len() as _;
-
- self.stream.extend_from_slice(value.as_bytes());
- self.stream.push(0); // terminator
- }
-
- self.stream.resize(round(self.stream.len(), 4), 0);
- StagedStrings(self)
- }
-}
-
-impl<'a> StagedStrings<'a> {
- pub fn stream(self) -> Vec<u8> {
- self.0.stream
- }
-
- pub fn index(&self, value: &str) -> u32 {
- if value.is_empty() {
- 0
- } else {
- self.0.map[value]
- }
- }
-}
diff --git a/vendor/windows-metadata/src/writer/imp/tables.rs b/vendor/windows-metadata/src/writer/imp/tables.rs
deleted file mode 100644
index 7b3450738..000000000
--- a/vendor/windows-metadata/src/writer/imp/tables.rs
+++ /dev/null
@@ -1,287 +0,0 @@
-#![allow(non_snake_case)]
-
-use super::*;
-
-#[derive(Default)]
-pub struct Tables {
- pub AssemblyRef: Vec<AssemblyRef>,
- pub ClassLayout: Vec<ClassLayout>,
- pub Constant: Vec<Constant>,
- pub CustomAttribute: Vec<CustomAttribute>,
- pub Field: Vec<Field>,
- pub GenericParam: Vec<GenericParam>,
- pub ImplMap: Vec<ImplMap>,
- pub InterfaceImpl: Vec<InterfaceImpl>,
- pub MemberRef: Vec<MemberRef>,
- pub MethodDef: Vec<MethodDef>,
- pub Module: Vec<Module>,
- pub ModuleRef: Vec<ModuleRef>,
- pub NestedClass: Vec<NestedClass>,
- pub Param: Vec<Param>,
- pub Property: Vec<Property>,
- pub TypeDef: Vec<TypeDef>,
- pub TypeRef: Vec<TypeRef>,
- pub TypeSpec: Vec<TypeSpec>,
-}
-
-#[derive(Default)]
-pub struct AssemblyRef {
- pub MajorVersion: u16,
- pub MinorVersion: u16,
- pub BuildNumber: u16,
- pub RevisionNumber: u16,
- pub Flags: u32,
- pub PublicKeyOrToken: u32,
- pub Name: u32,
- pub Culture: u32,
- pub HashValue: u32,
-}
-
-#[derive(Default)]
-pub struct ClassLayout {
- pub PackingSize: u16,
- pub ClassSize: u32,
- pub Parent: u32,
-}
-
-#[derive(Default)]
-pub struct Constant {
- pub Type: u16,
- pub Parent: u32,
- pub Value: u32,
-}
-
-#[derive(Default)]
-pub struct CustomAttribute {
- pub Parent: u32,
- pub Type: u32,
- pub Value: u32,
-}
-
-#[derive(Default)]
-pub struct Field {
- pub Flags: u16,
- pub Name: u32,
- pub Signature: u32,
-}
-
-#[derive(Default)]
-pub struct GenericParam {
- pub Number: u16,
- pub Flags: u16,
- pub Owner: u32,
- pub Name: u32,
-}
-
-#[derive(Default)]
-pub struct ImplMap {
- pub MappingFlags: u16,
- pub MemberForwarded: u32,
- pub ImportName: u32,
- pub ImportScope: u32,
-}
-
-#[derive(Default)]
-pub struct InterfaceImpl {
- pub Class: u32,
- pub Interface: u32,
-}
-
-#[derive(Default)]
-pub struct MemberRef {
- pub Class: u32,
- pub Name: u32,
- pub Signature: u32,
-}
-
-#[derive(Default)]
-pub struct MethodDef {
- pub RVA: u32,
- pub ImplFlags: u16,
- pub Flags: u16,
- pub Name: u32,
- pub Signature: u32,
- pub ParamList: u32,
-}
-
-#[derive(Default)]
-pub struct Module {
- pub Generation: u16,
- pub Name: u32,
- pub Mvid: u32,
- pub EncId: u32,
- pub EncBaseId: u32,
-}
-
-#[derive(Default)]
-pub struct ModuleRef {
- pub Name: u32,
-}
-
-#[derive(Default)]
-pub struct NestedClass {
- pub NestedClass: u32,
- pub EnclosingClass: u32,
-}
-
-#[derive(Default)]
-pub struct Param {
- pub Flags: u16,
- pub Sequence: u16,
- pub Name: u32,
-}
-
-#[derive(Default)]
-pub struct Property {
- pub Flags: u16,
- pub Name: u32,
- pub Type: u32,
-}
-
-#[derive(Default)]
-pub struct TypeDef {
- pub Flags: u32,
- pub TypeName: u32,
- pub TypeNamespace: u32,
- pub Extends: u32,
- pub FieldList: u32,
- pub MethodList: u32,
-}
-
-#[derive(Default)]
-pub struct TypeRef {
- pub ResolutionScope: u32,
- pub TypeName: u32,
- pub TypeNamespace: u32,
-}
-
-#[derive(Default)]
-pub struct TypeSpec {
- pub Signature: u32,
-}
-
-impl Tables {
- pub fn stream(self) -> Vec<u8> {
- let resolution_scope = coded_index_size(&[self.Module.len(), self.ModuleRef.len(), self.AssemblyRef.len(), self.TypeRef.len()]);
- let type_def_or_ref = coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]);
- let has_constant = coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]);
-
- let valid_tables: u64 = 1 << 0 | // Module
- 1 << 0x01 | // TypeRef
- 1 << 0x02 | // TypeDef
- 1 << 0x04 | // Field
- 1 << 0x06 | // MethodDef
- 1 << 0x08 | // Param
- 1 << 0x09 | // InterfaceImpl
- 1 << 0x0A | // MemberRef
- 1 << 0x0B | // Constant
- 1 << 0x0C | // CustomAttribute
- 1 << 0x0F | // ClassLayout
- 1 << 0x17 | // Property
- 1 << 0x1A | // ModuleRef
- 1 << 0x1B | // TypeSpec
- 1 << 0x1C | // ImplMap
- 1 << 0x23 | // AssemblyRef
- 1 << 0x29 | // NestedClass
- 1 << 0x2A; // GenericParam
-
- // The table stream header...
-
- let mut buffer = Vec::new();
- buffer.write_u32(0); // Reserved
- buffer.write_u8(2); // MajorVersion
- buffer.write_u8(0); // MinorVersion
- buffer.write_u8(0b111); // HeapSizes
- buffer.write_u8(0); // Reserved
- buffer.write_u64(valid_tables);
- buffer.write_u64(0); // Sorted
-
- // Followed by the length of each of the valid tables...
-
- buffer.write_u32(self.Module.len() as u32);
- buffer.write_u32(self.TypeRef.len() as u32);
- buffer.write_u32(self.TypeDef.len() as u32);
- buffer.write_u32(self.Field.len() as u32);
- buffer.write_u32(self.MethodDef.len() as u32);
- buffer.write_u32(self.Param.len() as u32);
- buffer.write_u32(self.InterfaceImpl.len() as u32);
- buffer.write_u32(self.MemberRef.len() as u32);
- buffer.write_u32(self.Constant.len() as u32);
- buffer.write_u32(self.CustomAttribute.len() as u32);
- buffer.write_u32(self.ClassLayout.len() as u32);
- buffer.write_u32(self.Property.len() as u32);
- buffer.write_u32(self.ModuleRef.len() as u32);
- buffer.write_u32(self.TypeSpec.len() as u32);
- buffer.write_u32(self.ImplMap.len() as u32);
- buffer.write_u32(self.AssemblyRef.len() as u32);
- buffer.write_u32(self.NestedClass.len() as u32);
- buffer.write_u32(self.GenericParam.len() as u32);
-
- // Followed by each table's rows...
-
- for x in self.Module {
- buffer.write_u16(x.Generation);
- buffer.write_u32(x.Name);
- buffer.write_u32(x.Mvid);
- buffer.write_u32(x.EncId);
- buffer.write_u32(x.EncBaseId);
- }
-
- for x in self.TypeRef {
- buffer.write_code(x.ResolutionScope, resolution_scope);
- buffer.write_u32(x.TypeName);
- buffer.write_u32(x.TypeNamespace);
- }
-
- for x in self.TypeDef {
- buffer.write_u32(x.Flags);
- buffer.write_u32(x.TypeName);
- buffer.write_u32(x.TypeNamespace);
- buffer.write_code(x.Extends, type_def_or_ref);
- buffer.write_index(x.FieldList, self.Field.len());
- buffer.write_index(x.MethodList, self.MethodDef.len());
- }
-
- for x in self.Field {
- buffer.write_u16(x.Flags);
- buffer.write_u32(x.Name);
- buffer.write_u32(x.Signature);
- }
-
- for x in self.MethodDef {
- buffer.write_u32(x.RVA);
- buffer.write_u16(x.ImplFlags);
- buffer.write_u16(x.Flags);
- buffer.write_u32(x.Name);
- buffer.write_u32(x.Signature);
- buffer.write_index(x.ParamList, self.Param.len());
- }
-
- for x in self.Param {
- buffer.write_u16(x.Flags);
- buffer.write_u16(x.Sequence);
- buffer.write_u32(x.Name);
- }
-
- for x in self.Constant {
- buffer.write_u16(x.Type);
- buffer.write_code(x.Parent, has_constant);
- buffer.write_u32(x.Value);
- }
-
- for x in self.AssemblyRef {
- buffer.write_u16(x.MajorVersion);
- buffer.write_u16(x.MinorVersion);
- buffer.write_u16(x.BuildNumber);
- buffer.write_u16(x.RevisionNumber);
- buffer.write_u32(x.Flags);
- buffer.write_u32(x.PublicKeyOrToken);
- buffer.write_u32(x.Name);
- buffer.write_u32(x.Culture);
- buffer.write_u32(x.HashValue);
- }
-
- buffer.resize(round(buffer.len(), 4), 0);
- buffer
- }
-}
diff --git a/vendor/windows-metadata/src/writer/mod.rs b/vendor/windows-metadata/src/writer/mod.rs
deleted file mode 100644
index 8dcf332b8..000000000
--- a/vendor/windows-metadata/src/writer/mod.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-mod imp;
-use super::*;
-
-// Generates an in-memory .winmd file.
-pub fn write(name: &str, winrt: bool, items: &[Item], assemblies: &[&str]) -> Vec<u8> {
- imp::write(name, winrt, items, assemblies)
-}
-
-pub enum Item {
- Struct(Struct),
- Enum(Enum),
- Interface(Interface),
-}
-
-pub struct Struct {
- pub namespace: String,
- pub name: String,
- pub fields: Vec<Field>,
-}
-
-pub struct Enum {
- pub namespace: String,
- pub name: String,
- pub constants: Vec<Constant>,
-}
-
-pub struct Interface {
- pub namespace: String,
- pub name: String,
- pub methods: Vec<Method>,
-}
-
-pub struct Field {
- pub name: String,
- pub ty: Type,
-}
-
-pub struct Constant {
- pub name: String,
- pub value: Value,
-}
-
-pub struct Method {
- pub name: String,
- pub return_type: Type,
- pub params: Vec<Param>,
-}
-
-pub struct Param {
- pub name: String,
- pub ty: Type,
- pub flags: ParamFlags,
-}
-
-flags!(ParamFlags, u32);
-impl ParamFlags {
- pub const INPUT: Self = Self(0x1);
- pub const OUTPUT: Self = Self(0x2);
- pub const OPTIONAL: Self = Self(0x10);
-}
-
-pub enum Type {
- Void,
- Bool,
- Char,
- I8,
- U8,
- I16,
- U16,
- I32,
- U32,
- I64,
- U64,
- F32,
- F64,
- ISize,
- USize,
- String,
- Named((String, String)),
-}
-
-pub enum Value {
- Bool(bool),
- U8(u8),
- I8(i8),
- U16(u16),
- I16(i16),
- U32(u32),
- I32(i32),
- U64(u64),
- I64(i64),
- F32(f32),
- F64(f64),
- String(String),
-}