diff options
Diffstat (limited to 'vendor/windows-metadata/src/reader')
-rw-r--r-- | vendor/windows-metadata/src/reader/blob.rs | 147 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/codes.rs | 122 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/file.rs | 537 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/filter.rs | 157 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/guid.rs | 40 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/mod.rs | 1833 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/row.rs | 15 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/tree.rs | 31 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/type.rs | 152 | ||||
-rw-r--r-- | vendor/windows-metadata/src/reader/type_name.rs | 75 |
10 files changed, 0 insertions, 3109 deletions
diff --git a/vendor/windows-metadata/src/reader/blob.rs b/vendor/windows-metadata/src/reader/blob.rs deleted file mode 100644 index b7d4880d0..000000000 --- a/vendor/windows-metadata/src/reader/blob.rs +++ /dev/null @@ -1,147 +0,0 @@ -use super::*; -use std::convert::*; - -pub struct Blob<'a> { - pub file: usize, - pub slice: &'a [u8], -} - -impl<'a> std::ops::Deref for Blob<'a> { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - self.slice - } -} - -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) - } else if self[0] & 0xC0 == 0x80 { - ((((self[0] & 0x3F) as usize) << 8) | self[1] as usize, 2) - } else { - ((((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 { - self.offset(offset); - true - } else { - 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 { - break; - } else { - self.offset(offset); - mods.push(TypeDefOrRef::decode(self.file, self.read_usize())) - } - } - 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 { - let slice = slice.chunks_exact(2).take(slice.len() / 2).map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap())).collect::<Vec<u16>>(); - String::from_utf16_lossy(&slice) - } else { - let slice = unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const u16, slice.len() / 2) }; - 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() { - 0 => false, - 1 => true, - _ => 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 { - 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()), - _ => 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/reader/codes.rs deleted file mode 100644 index a6cfa4885..000000000 --- a/vendor/windows-metadata/src/reader/codes.rs +++ /dev/null @@ -1,122 +0,0 @@ -use super::*; - -pub trait Decode { - fn decode(file: usize, code: usize) -> Self; -} - -pub enum AttributeType { - MemberRef(MemberRef), -} - -impl Decode for AttributeType { - fn decode(file: usize, code: usize) -> Self { - let (kind, row) = (code & ((1 << 3) - 1), (code >> 3) - 1); - match kind { - 3 => Self::MemberRef(MemberRef(Row::new(row, TABLE_MEMBERREF, file))), - _ => unimplemented!(), - } - } -} - -pub enum HasAttribute { - MethodDef(MethodDef), - Field(Field), - TypeRef(TypeRef), - TypeDef(TypeDef), - Param(Param), - InterfaceImpl(InterfaceImpl), - MemberRef(MemberRef), - TypeSpec(TypeSpec), - GenericParam(GenericParam), -} - -impl HasAttribute { - pub fn encode(&self) -> usize { - (match self { - Self::MethodDef(row) => (row.0.row + 1) << 5, - Self::Field(row) => ((row.0.row + 1) << 5) | 1, - Self::TypeRef(row) => ((row.0.row + 1) << 5) | 2, - Self::TypeDef(row) => ((row.0.row + 1) << 5) | 3, - Self::Param(row) => ((row.0.row + 1) << 5) | 4, - Self::InterfaceImpl(row) => ((row.0.row + 1) << 5) | 5, - Self::MemberRef(row) => ((row.0.row + 1) << 5) | 6, - Self::TypeSpec(row) => ((row.0.row + 1) << 5) | 13, - Self::GenericParam(row) => ((row.0.row + 1) << 5) | 19, - }) as _ - } -} - -#[derive(Clone)] -pub enum HasConstant { - Field(Field), -} - -impl HasConstant { - pub fn encode(&self) -> usize { - (match self { - Self::Field(row) => (row.0.row + 1) << 2, - }) as _ - } -} - -#[derive(Clone)] -pub enum MemberForwarded { - MethodDef(MethodDef), -} - -impl MemberForwarded { - pub fn encode(&self) -> usize { - (match self { - Self::MethodDef(value) => ((value.0.row + 1) << 1) | 1, - }) as _ - } -} - -pub enum MemberRefParent { - TypeRef(TypeRef), -} - -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!(), - } - } -} - -#[derive(Copy, Clone)] -pub enum TypeDefOrRef { - None, - TypeDef(TypeDef), - TypeRef(TypeRef), - TypeSpec(TypeSpec), -} - -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!(), - } - } -} - -pub enum TypeOrMethodDef { - TypeDef(TypeDef), -} - -impl TypeOrMethodDef { - pub fn encode(&self) -> usize { - (match self { - Self::TypeDef(value) => (value.0.row + 1) << 1, - }) as _ - } -} 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/filter.rs b/vendor/windows-metadata/src/reader/filter.rs deleted file mode 100644 index 4b6651fb6..000000000 --- a/vendor/windows-metadata/src/reader/filter.rs +++ /dev/null @@ -1,157 +0,0 @@ -use super::*; - -#[derive(Default)] -pub struct Filter<'a>(Vec<(&'a str, bool)>); - -impl<'a> Filter<'a> { - pub fn new(include: &[&'a str], exclude: &[&'a str]) -> Self { - let mut rules = vec![]; - - for include in include { - rules.push((*include, true)); - } - - for exclude in exclude { - rules.push((*exclude, false)); - } - - rules.sort_unstable_by(|left, right| { - let left = (left.0.len(), !left.1); - let right = (right.0.len(), !right.1); - left.cmp(&right).reverse() - }); - - Self(rules) - } - - pub fn includes_namespace(&self, namespace: &str) -> bool { - if self.is_empty() { - return true; - } - - for rule in &self.0 { - if rule.1 { - // include - if rule.0.starts_with(namespace) { - return true; - } - if namespace.starts_with(rule.0) { - return true; - } - } else { - // exclude - if namespace.starts_with(rule.0) { - return false; - } - } - } - - 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 { - if self.is_empty() { - return true; - } - - for rule in &self.0 { - if match_type_name(rule.0, type_name.namespace, type_name.name) { - return rule.1; - } - } - - false - } - - fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -fn match_type_name(rule: &str, namespace: &str, name: &str) -> bool { - if rule.len() <= namespace.len() { - return namespace.starts_with(rule); - } - - if !rule.starts_with(namespace) { - return false; - } - - if rule.as_bytes()[namespace.len()] != b'.' { - return false; - } - - name.starts_with(&rule[namespace.len() + 1..]) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn includes_type_name(filter: &Filter, full_name: &str) -> bool { - filter.includes_type_name(TypeName::parse(full_name)) - } - - #[test] - fn test_namespace() { - let include = ["N1.N2"]; - let exclude = ["N1.N2.N3"]; - let f = Filter::new(&include, &exclude); - - assert!(f.includes_namespace("N1")); - assert!(f.includes_namespace("N1.N2")); - assert!(f.includes_namespace("N1.N2.N4")); - - assert!(!f.includes_namespace("N1.N2.N3")); - assert!(!f.includes_namespace("N1.N2.N3.N4")); - } - - #[test] - fn test_simple() { - let include = ["N1", "N3", "N3.N4.N5"]; - let exclude = ["N2", "N3.N4"]; - let f = Filter::new(&include, &exclude); - - assert!(!f.is_empty()); - - assert!(!includes_type_name(&f, "NN.T")); - - assert!(includes_type_name(&f, "N1.T")); - assert!(includes_type_name(&f, "N3.T")); - - assert!(!includes_type_name(&f, "N2.T")); - assert!(!includes_type_name(&f, "N3.N4.T")); - - assert!(includes_type_name(&f, "N3.N4.N5.T")); - } - - #[test] - fn filter_excludes_same_length() { - let include = ["N.N1", "N.N2"]; - let exclude = ["N.N3", "N.N4"]; - let f = Filter::new(&include, &exclude); - - assert!(!f.is_empty()); - - assert!(includes_type_name(&f, "N.N1.T")); - assert!(includes_type_name(&f, "N.N2.T")); - - assert!(!includes_type_name(&f, "N.N3.T")); - assert!(!includes_type_name(&f, "N.N4.T")); - } - - #[test] - fn filter_exclude_include_precedence() { - let include = ["N.T"]; - let exclude = ["N.T"]; - let f = Filter::new(&include, &exclude); - - assert!(!f.is_empty()); - - assert!(!includes_type_name(&f, "N.T")); - } -} diff --git a/vendor/windows-metadata/src/reader/guid.rs b/vendor/windows-metadata/src/reader/guid.rs deleted file mode 100644 index 96444b8b2..000000000 --- a/vendor/windows-metadata/src/reader/guid.rs +++ /dev/null @@ -1,40 +0,0 @@ -#![allow(clippy::many_single_char_names)] - -use super::*; - -#[derive(Clone, PartialEq, Eq, Default)] -pub struct GUID(pub u32, pub u16, pub u16, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8); - -impl GUID { - pub fn from_args(args: &[(String, Value)]) -> Self { - fn unwrap_u32(value: &Value) -> u32 { - match value { - Value::U32(value) => *value, - _ => unimplemented!(), - } - } - fn unwrap_u16(value: &Value) -> u16 { - match value { - Value::U16(value) => *value, - _ => unimplemented!(), - } - } - fn unwrap_u8(value: &Value) -> u8 { - match value { - Value::U8(value) => *value, - _ => unimplemented!(), - } - } - Self(unwrap_u32(&args[0].1), unwrap_u16(&args[1].1), unwrap_u16(&args[2].1), unwrap_u8(&args[3].1), unwrap_u8(&args[4].1), unwrap_u8(&args[5].1), unwrap_u8(&args[6].1), unwrap_u8(&args[7].1), unwrap_u8(&args[8].1), unwrap_u8(&args[9].1), unwrap_u8(&args[10].1)) - } - - pub fn from_string_args(args: &[&str]) -> Self { - Self(args[0].parse().unwrap(), args[1].parse().unwrap(), args[2].parse().unwrap(), args[3].parse().unwrap(), args[4].parse().unwrap(), args[5].parse().unwrap(), args[6].parse().unwrap(), args[7].parse().unwrap(), args[8].parse().unwrap(), args[9].parse().unwrap(), args[10].parse().unwrap()) - } -} - -impl std::fmt::Debug for GUID { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:08x?}-{:04x?}-{:04x?}-{:02x?}{:02x?}-{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}", self.0, self.1, self.2, self.3, self.4, self.5, self.6, self.7, self.8, self.9, self.10) - } -} diff --git a/vendor/windows-metadata/src/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(¶m.ty) && (!param.ty.is_pointer() || self.type_is_blittable(¶m.ty.deref())) { - param.kind = SignatureParamKind::ValueType; - } else if self.type_is_blittable(¶m.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(¶m.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(¶m.ty, cfg)); - } - pub fn signature_param_is_borrowed(&self, param: &SignatureParam) -> bool { - self.type_is_borrowed(¶m.ty) - } - pub fn signature_param_is_failible_param(&self, param: &SignatureParam) -> bool { - self.type_is_non_exclusive_winrt_interface(¶m.ty) - } - pub fn signature_param_is_trivially_convertible(&self, param: &SignatureParam) -> bool { - self.type_is_trivially_convertible(¶m.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(¶m.ty) || self.type_is_non_exclusive_winrt_interface(¶m.ty) || self.type_is_trivially_convertible(¶m.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(¶m.ty.deref()) > 16 { - return false; - } - // TODO: find a way to treat this like COM interface result values. - !self.type_is_callback(¶m.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/reader/type_name.rs b/vendor/windows-metadata/src/reader/type_name.rs deleted file mode 100644 index 2e7b40808..000000000 --- a/vendor/windows-metadata/src/reader/type_name.rs +++ /dev/null @@ -1,75 +0,0 @@ -#[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"); - pub const Object: Self = Self::from_const("System", "Object"); - pub const GUID: Self = Self::from_const("System", "Guid"); - pub const Type: Self = Self::from_const("System", "Type"); - pub const Attribute: Self = Self::from_const("System", "Attribute"); - pub const IsConst: Self = Self::from_const("System.Runtime.CompilerServices", "IsConst"); - - pub const HResult: Self = Self::from_const("Windows.Foundation", "HResult"); - pub const IAsyncAction: Self = Self::from_const("Windows.Foundation", "IAsyncAction"); - pub const IAsyncActionWithProgress: Self = Self::from_const("Windows.Foundation", "IAsyncActionWithProgress"); - pub const IAsyncOperation: Self = Self::from_const("Windows.Foundation", "IAsyncOperation"); - pub const IAsyncOperationWithProgress: Self = Self::from_const("Windows.Foundation", "IAsyncOperationWithProgress"); - - pub const Matrix3x2: Self = Self::from_const("Windows.Foundation.Numerics", "Matrix3x2"); - pub const Matrix4x4: Self = Self::from_const("Windows.Foundation.Numerics", "Matrix4x4"); - - pub const IIterable: Self = Self::from_const("Windows.Foundation.Collections", "IIterable"); - pub const IIterator: Self = Self::from_const("Windows.Foundation.Collections", "IIterator"); - pub const IVectorView: Self = Self::from_const("Windows.Foundation.Collections", "IVectorView"); - pub const IVector: Self = Self::from_const("Windows.Foundation.Collections", "IVector"); - - pub const NTSTATUS: Self = Self::from_const("Windows.Win32.Foundation", "NTSTATUS"); - pub const PWSTR: Self = Self::from_const("Windows.Win32.Foundation", "PWSTR"); - pub const PSTR: Self = Self::from_const("Windows.Win32.Foundation", "PSTR"); - pub const BSTR: Self = Self::from_const("Windows.Win32.Foundation", "BSTR"); - 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 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"); - pub const IUnknown: Self = Self::from_const("Windows.Win32.System.Com", "IUnknown"); - pub const HSTRING: Self = Self::from_const("Windows.Win32.System.WinRT", "HSTRING"); - pub const IInspectable: Self = Self::from_const("Windows.Win32.System.WinRT", "IInspectable"); - pub const IRestrictedErrorInfo: Self = Self::from_const("Windows.Win32.System.WinRT", "IRestrictedErrorInfo"); - pub const IDispatch: Self = Self::from_const("Windows.Win32.System.Com", "IDispatch"); - - const fn from_const(namespace: &'static str, name: &'static str) -> Self { - Self { namespace, name } - } - - pub fn new(namespace: &'a str, name: &'a str) -> Self { - Self { namespace, name: trim_tick(name) } - } - - pub fn parse(full_name: &'a str) -> Self { - let index = full_name.rfind('.').expect("Expected full name separated with `.`"); - Self { namespace: &full_name[0..index], name: &full_name[index + 1..] } - } -} - -impl<'a> std::fmt::Display for TypeName<'a> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - 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 - } -} |