summaryrefslogtreecommitdiffstats
path: root/vendor/windows-bindgen/src/winmd
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/windows-bindgen/src/winmd')
-rw-r--r--vendor/windows-bindgen/src/winmd/from_reader.rs141
-rw-r--r--vendor/windows-bindgen/src/winmd/mod.rs7
-rw-r--r--vendor/windows-bindgen/src/winmd/verify.rs31
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/blobs.rs48
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/codes.rs71
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/file.rs134
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/mod.rs329
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/strings.rs35
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/tables.rs361
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/traits.rs66
-rw-r--r--vendor/windows-bindgen/src/winmd/writer/type.rs80
11 files changed, 1303 insertions, 0 deletions
diff --git a/vendor/windows-bindgen/src/winmd/from_reader.rs b/vendor/windows-bindgen/src/winmd/from_reader.rs
new file mode 100644
index 000000000..b535caed0
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/from_reader.rs
@@ -0,0 +1,141 @@
+use super::*;
+use crate::winmd::{self, writer};
+use metadata::RowReader;
+
+pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, config: std::collections::BTreeMap<&str, &str>, output: &str) -> crate::Result<()> {
+ let mut writer = winmd::Writer::new(output);
+
+ // TODO: do we need any configuration values for winmd generation?
+ // Maybe per-namespace winmd files for namespace-splitting - be sure to use
+ // the same key as for winmd generation.
+
+ if let Some((key, _)) = config.first_key_value() {
+ return Err(crate::Error::new(&format!("invalid configuration value `{key}`")));
+ }
+
+ // TODO: just use the reader directly since we now have everything in the reader, there's no need to abstract
+ // away the source format. Few reprs is always better.
+
+ for item in reader.items(filter) {
+ // TODO: cover all variants
+ let metadata::Item::Type(def) = item else {
+ continue;
+ };
+
+ let generics = &metadata::type_def_generics(reader, def);
+
+ let extends = if let Some(extends) = reader.type_def_extends(def) { writer.insert_type_ref(extends.namespace, extends.name) } else { 0 };
+
+ writer.tables.TypeDef.push(writer::TypeDef {
+ Extends: extends,
+ FieldList: writer.tables.Field.len() as u32,
+ Flags: reader.type_def_flags(def).0,
+ MethodList: writer.tables.MethodDef.len() as u32,
+ TypeName: writer.strings.insert(reader.type_def_name(def)),
+ TypeNamespace: writer.strings.insert(reader.type_def_namespace(def)),
+ });
+
+ for generic in reader.type_def_generics(def) {
+ writer.tables.GenericParam.push(writer::GenericParam {
+ Number: reader.generic_param_number(generic),
+ Flags: 0,
+ Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1).encode(),
+ Name: writer.strings.insert(reader.generic_param_name(generic)),
+ });
+ }
+
+ for imp in reader.type_def_interface_impls(def) {
+ let ty = reader.interface_impl_type(imp, generics);
+ let ty = winmd_type(reader, &ty);
+
+ let reference = match &ty {
+ winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => writer.insert_type_ref(&type_name.namespace, &type_name.name),
+ winmd::Type::TypeRef(_) => writer.insert_type_spec(ty),
+ winmd::Type::IUnknown => writer.insert_type_ref("Windows.Win32.System.Com", "IUnknown"),
+ winmd::Type::IInspectable => writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable"),
+ rest => unimplemented!("{rest:?}"),
+ };
+
+ writer.tables.InterfaceImpl.push(writer::InterfaceImpl { Class: writer.tables.TypeDef.len() as u32 - 1, Interface: reference });
+ }
+
+ // TODO: if the class is "Apis" then should we sort the fields (constants) and methods (functions) for stability
+
+ for field in reader.type_def_fields(def) {
+ let ty = winmd_type(reader, &reader.field_type(field, Some(def)));
+ let signature = writer.insert_field_sig(&ty);
+
+ writer.tables.Field.push(writer::Field { Flags: reader.field_flags(field).0, Name: writer.strings.insert(reader.field_name(field)), Signature: signature });
+ }
+
+ for method in reader.type_def_methods(def) {
+ let signature = reader.method_def_signature(method, generics);
+ let return_type = winmd_type(reader, &signature.return_type);
+ let param_types: Vec<Type> = signature.params.iter().map(|param| winmd_type(reader, param)).collect();
+
+ let signature = writer.insert_method_sig(signature.call_flags, &return_type, &param_types);
+
+ writer.tables.MethodDef.push(winmd::MethodDef {
+ RVA: 0,
+ ImplFlags: reader.method_def_impl_flags(method).0,
+ Flags: reader.method_def_flags(method).0,
+ Name: writer.strings.insert(reader.method_def_name(method)),
+ Signature: signature,
+ ParamList: writer.tables.Param.len() as u32,
+ });
+
+ for param in reader.method_def_params(method) {
+ writer.tables.Param.push(writer::Param { Flags: reader.param_flags(param).0, Sequence: reader.param_sequence(param), Name: writer.strings.insert(reader.param_name(param)) });
+ }
+ }
+ }
+
+ // TODO: In theory, `config` could instruct this function to balance the types across a number of winmd files
+ // like mdmerge supports for namespace-splitting.
+ crate::write_to_file(output, writer.into_stream()).map_err(|err| err.with_path(output))
+}
+
+// TODO: keep the basic type conversion
+fn winmd_type(reader: &metadata::Reader, ty: &metadata::Type) -> winmd::Type {
+ match ty {
+ metadata::Type::Void => winmd::Type::Void,
+ metadata::Type::Bool => winmd::Type::Bool,
+ metadata::Type::Char => winmd::Type::Char,
+ metadata::Type::I8 => winmd::Type::I8,
+ metadata::Type::U8 => winmd::Type::U8,
+ metadata::Type::I16 => winmd::Type::I16,
+ metadata::Type::U16 => winmd::Type::U16,
+ metadata::Type::I32 => winmd::Type::I32,
+ metadata::Type::U32 => winmd::Type::U32,
+ metadata::Type::I64 => winmd::Type::I64,
+ metadata::Type::U64 => winmd::Type::U64,
+ metadata::Type::F32 => winmd::Type::F32,
+ metadata::Type::F64 => winmd::Type::F64,
+ metadata::Type::ISize => winmd::Type::ISize,
+ metadata::Type::USize => winmd::Type::USize,
+ metadata::Type::String => winmd::Type::String,
+ metadata::Type::GUID => winmd::Type::GUID,
+ metadata::Type::IUnknown => winmd::Type::IUnknown,
+ metadata::Type::IInspectable => winmd::Type::IInspectable,
+ metadata::Type::HRESULT => winmd::Type::HRESULT,
+ metadata::Type::PSTR => winmd::Type::PSTR,
+ metadata::Type::PWSTR => winmd::Type::PWSTR,
+ metadata::Type::PCSTR => winmd::Type::PCSTR,
+ metadata::Type::PCWSTR => winmd::Type::PCWSTR,
+ metadata::Type::BSTR => winmd::Type::BSTR,
+ metadata::Type::TypeName => winmd::Type::TypeName,
+ metadata::Type::TypeDef(def, generics) => winmd::Type::TypeRef(winmd::TypeName {
+ namespace: reader.type_def_namespace(*def).to_string(),
+ name: reader.type_def_name(*def).to_string(),
+ generics: generics.iter().map(|ty| winmd_type(reader, ty)).collect(),
+ }),
+ metadata::Type::GenericParam(generic) => winmd::Type::GenericParam(reader.generic_param_number(*generic)),
+ metadata::Type::ConstRef(ty) => winmd::Type::ConstRef(Box::new(winmd_type(reader, ty))),
+ metadata::Type::WinrtArrayRef(ty) => winmd::Type::WinrtArrayRef(Box::new(winmd_type(reader, ty))),
+ metadata::Type::WinrtArray(ty) => winmd::Type::WinrtArray(Box::new(winmd_type(reader, ty))),
+ metadata::Type::MutPtr(ty, pointers) => winmd::Type::MutPtr(Box::new(winmd_type(reader, ty)), *pointers),
+ metadata::Type::ConstPtr(ty, pointers) => winmd::Type::ConstPtr(Box::new(winmd_type(reader, ty)), *pointers),
+ metadata::Type::Win32Array(ty, len) => winmd::Type::Win32Array(Box::new(winmd_type(reader, ty)), *len),
+ rest => unimplemented!("{rest:?}"),
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/mod.rs b/vendor/windows-bindgen/src/winmd/mod.rs
new file mode 100644
index 000000000..f01afa218
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/mod.rs
@@ -0,0 +1,7 @@
+mod from_reader;
+mod verify;
+pub mod writer;
+use super::*;
+pub use from_reader::from_reader;
+pub use verify::verify;
+pub use writer::*;
diff --git a/vendor/windows-bindgen/src/winmd/verify.rs b/vendor/windows-bindgen/src/winmd/verify.rs
new file mode 100644
index 000000000..f10bd6524
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/verify.rs
@@ -0,0 +1,31 @@
+use super::*;
+use metadata::RowReader;
+
+pub fn verify(reader: &metadata::Reader, filter: &metadata::Filter) -> crate::Result<()> {
+ for item in reader.items(filter) {
+ // TODO: cover all variants
+ let metadata::Item::Type(def) = item else {
+ continue;
+ };
+
+ let generics = &metadata::type_def_generics(reader, def);
+
+ reader.type_def_fields(def).try_for_each(|field| not_type_ref(reader, &reader.field_type(field, Some(def))))?;
+
+ reader.type_def_methods(def).try_for_each(|method| {
+ let sig = reader.method_def_signature(method, generics);
+ not_type_ref(reader, &sig.return_type)?;
+
+ sig.params.iter().try_for_each(|param| not_type_ref(reader, param))
+ })?;
+ }
+
+ Ok(())
+}
+
+fn not_type_ref(reader: &metadata::Reader, ty: &metadata::Type) -> crate::Result<()> {
+ if let metadata::Type::TypeRef(ty) = ty {
+ return Err(crate::Error::new(&format!("missing type definition `{}`", reader.type_def_or_ref(*ty))));
+ }
+ Ok(())
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/blobs.rs b/vendor/windows-bindgen/src/winmd/writer/blobs.rs
new file mode 100644
index 000000000..5201a32d0
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/blobs.rs
@@ -0,0 +1,48 @@
+use super::*;
+use std::collections::hash_map::*;
+
+pub struct Blobs {
+ map: HashMap<Vec<u8>, u32>,
+ stream: Vec<u8>,
+}
+
+impl Default for Blobs {
+ fn default() -> Self {
+ Self { map: Default::default(), stream: vec![0] }
+ }
+}
+
+impl Blobs {
+ pub fn insert(&mut self, value: &[u8]) -> u32 {
+ if value.is_empty() {
+ return 0;
+ }
+
+ match self.map.entry(value.to_vec()) {
+ Entry::Vacant(entry) => {
+ let offset = *entry.insert(self.stream.len() as u32);
+ let len = value.len();
+ match len {
+ 0..=0x7F => self.stream.push(len as u8),
+ 0x80..=0x3FFF => {
+ self.stream.push((0x80 | len >> 8) as u8);
+ self.stream.push((0xFF & len) as u8);
+ }
+ _ => {
+ self.stream.push((0xC0 | len >> 24) as u8);
+ self.stream.push((0xFF & len >> 16) as u8);
+ self.stream.push((0xFF & len >> 8) as u8);
+ self.stream.push((0xFF & len) as u8);
+ }
+ }
+ self.stream.extend_from_slice(value);
+ offset
+ }
+ Entry::Occupied(entry) => *entry.get(),
+ }
+ }
+
+ pub fn into_stream(self) -> Vec<u8> {
+ self.stream.into_stream()
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/codes.rs b/vendor/windows-bindgen/src/winmd/writer/codes.rs
new file mode 100644
index 000000000..c5aa789e0
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/codes.rs
@@ -0,0 +1,71 @@
+#![allow(dead_code, clippy::enum_variant_names)]
+
+/// A `ResolutionScope` is an index into a certain table indicating the scope in which a TypeRef can be resolved.
+#[derive(Clone)]
+pub enum ResolutionScope {
+ Module(u32),
+ ModuleRef(u32),
+ AssemblyRef(u32),
+ TypeRef(u32),
+}
+
+impl ResolutionScope {
+ pub fn encode(&self) -> u32 {
+ match self {
+ Self::Module(row) => (row + 1) << 2,
+ Self::ModuleRef(row) => ((row + 1) << 2) + 1,
+ Self::AssemblyRef(row) => ((row + 1) << 2) + 2,
+ Self::TypeRef(row) => ((row + 1) << 2) + 3,
+ }
+ }
+}
+
+/// A `TypeDefOrRef` is an index into a certain table used to locate a type definition.
+#[derive(Clone)]
+pub enum TypeDefOrRef {
+ TypeDef(u32),
+ TypeRef(u32),
+ TypeSpec(u32),
+}
+
+impl TypeDefOrRef {
+ pub fn encode(&self) -> u32 {
+ match self {
+ Self::TypeDef(row) => (row + 1) << 2,
+ Self::TypeRef(row) => ((row + 1) << 2) + 1,
+ Self::TypeSpec(row) => ((row + 1) << 2) + 2,
+ }
+ }
+}
+
+/// A `HasConstant` is an index into a certain table used to identify the parent of a row in the `Constant` table.
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub enum HasConstant {
+ Field(u32),
+ Param(u32),
+ Property(u32),
+}
+
+impl HasConstant {
+ pub fn encode(&self) -> u32 {
+ match self {
+ Self::Field(row) => (row + 1) << 2,
+ Self::Param(row) => ((row + 1) << 2) + 1,
+ Self::Property(row) => ((row + 1) << 2) + 2,
+ }
+ }
+}
+
+/// A `TypeOrMethodDef` is an index into a certain table used to locate the owner of a generic parameter.
+#[derive(Clone)]
+pub enum TypeOrMethodDef {
+ TypeDef(u32),
+}
+
+impl TypeOrMethodDef {
+ pub fn encode(&self) -> u32 {
+ match self {
+ Self::TypeDef(row) => (row + 1) << 1,
+ }
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/file.rs b/vendor/windows-bindgen/src/winmd/writer/file.rs
new file mode 100644
index 000000000..b452ba559
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/file.rs
@@ -0,0 +1,134 @@
+use super::*;
+use metadata::imp::*;
+use std::mem::*;
+
+pub fn write(mut tables: Vec<u8>, mut strings: Vec<u8>, mut blobs: Vec<u8>) -> Vec<u8> {
+ if [tables.len(), strings.len(), blobs.len()].iter().any(|len| *len > u32::MAX as usize) {
+ panic!("heap too large");
+ }
+
+ unsafe {
+ let mut guids = vec![0; 16]; // zero guid
+ let size_of_streams = tables.len() + guids.len() + strings.len() + blobs.len();
+
+ let mut dos: IMAGE_DOS_HEADER = zeroed();
+ dos.e_magic = IMAGE_DOS_SIGNATURE;
+ dos.e_lfarlc = 64;
+ dos.e_lfanew = size_of::<IMAGE_DOS_HEADER>() as i32;
+
+ let mut file: IMAGE_FILE_HEADER = zeroed();
+ file.Machine = IMAGE_FILE_MACHINE_I386;
+ file.NumberOfSections = 1;
+ file.SizeOfOptionalHeader = size_of::<IMAGE_OPTIONAL_HEADER32>() as u16;
+ file.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE;
+
+ let mut optional: IMAGE_OPTIONAL_HEADER32 = zeroed();
+ optional.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ optional.MajorLinkerVersion = 11;
+ optional.SizeOfInitializedData = 1024;
+ optional.ImageBase = 0x400000;
+ optional.SectionAlignment = SECTION_ALIGNMENT;
+ optional.FileAlignment = 512;
+ optional.MajorOperatingSystemVersion = 6;
+ optional.MinorOperatingSystemVersion = 2;
+ optional.MajorSubsystemVersion = 6;
+ optional.MinorSubsystemVersion = 2;
+ optional.SizeOfHeaders = 512;
+ optional.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
+ optional.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_NO_SEH | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
+ optional.SizeOfStackReserve = 0x100000;
+ optional.SizeOfHeapReserve = 4096;
+ optional.LoaderFlags = 0x100000;
+ optional.NumberOfRvaAndSizes = 16;
+
+ let mut section: IMAGE_SECTION_HEADER = zeroed();
+ section.Name = *b".text\0\0\0";
+ section.Characteristics = 0x4000_0020;
+ section.VirtualAddress = SECTION_ALIGNMENT;
+
+ let mut clr: IMAGE_COR20_HEADER = zeroed();
+ clr.cb = size_of::<IMAGE_COR20_HEADER>() as u32;
+ clr.MajorRuntimeVersion = 2;
+ clr.MinorRuntimeVersion = 5;
+ clr.Flags = 1;
+
+ let metadata = METADATA_HEADER {
+ signature: METADATA_SIGNATURE,
+ major_version: 1,
+ minor_version: 1,
+ length: 20,
+ version: *b"WindowsRuntime 1.4\0\0",
+ streams: 4,
+ ..Default::default()
+ };
+
+ type TablesHeader = StreamHeader<4>;
+ type StringsHeader = StreamHeader<12>;
+ type GuidsHeader = StreamHeader<8>;
+ type BlobsHeader = StreamHeader<8>;
+
+ let size_of_stream_headers = size_of::<TablesHeader>() + size_of::<StringsHeader>() + size_of::<GuidsHeader>() + size_of::<BlobsHeader>();
+ let size_of_image = optional.FileAlignment as usize + size_of::<IMAGE_COR20_HEADER>() + size_of::<METADATA_HEADER>() + size_of_stream_headers + size_of_streams;
+
+ optional.SizeOfImage = round(size_of_image, optional.SectionAlignment as usize) as u32;
+ section.Misc.VirtualSize = size_of_image as u32 - optional.FileAlignment;
+ section.SizeOfRawData = round(section.Misc.VirtualSize as usize, optional.FileAlignment as usize) as u32;
+
+ optional.DataDirectory[14] = IMAGE_DATA_DIRECTORY { VirtualAddress: SECTION_ALIGNMENT, Size: size_of::<IMAGE_COR20_HEADER>() as u32 };
+ section.PointerToRawData = optional.FileAlignment;
+ clr.MetaData.VirtualAddress = SECTION_ALIGNMENT + size_of::<IMAGE_COR20_HEADER>() as u32;
+ clr.MetaData.Size = section.Misc.VirtualSize - size_of::<IMAGE_COR20_HEADER>() as u32;
+
+ let mut buffer = Vec::<u8>::new();
+
+ buffer.write_header(&dos);
+ buffer.write_u32(IMAGE_NT_SIGNATURE);
+ buffer.write_header(&file);
+ buffer.write_header(&optional);
+ buffer.write_header(&section);
+ debug_assert!(buffer.len() < optional.FileAlignment as usize);
+ buffer.resize(optional.FileAlignment as usize, 0);
+ buffer.write_header(&clr);
+ let metadata_offset = buffer.len();
+ buffer.write_header(&metadata);
+
+ let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers;
+ let tables_header = TablesHeader::new(stream_offset as u32, tables.len() as u32, b"#~\0\0");
+ let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as u32, b"#Strings\0\0\0\0");
+ let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as u32, b"#GUID\0\0\0");
+ let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as u32, b"#Blob\0\0\0");
+
+ buffer.write_header(&tables_header);
+ buffer.write_header(&strings_header);
+ buffer.write_header(&guids_header);
+ buffer.write_header(&blobs_header);
+
+ buffer.append(&mut tables);
+ buffer.append(&mut strings);
+ buffer.append(&mut guids);
+ buffer.append(&mut blobs);
+
+ assert_eq!(clr.MetaData.Size as usize, buffer.len() - metadata_offset);
+ assert_eq!(size_of_image, buffer.len());
+
+ buffer
+ }
+}
+
+const SECTION_ALIGNMENT: u32 = 4096;
+
+#[repr(C)]
+struct StreamHeader<const LEN: usize> {
+ offset: u32,
+ size: u32,
+ name: [u8; LEN],
+}
+
+impl<const LEN: usize> StreamHeader<LEN> {
+ fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self {
+ Self { offset, size, name: *name }
+ }
+ fn next_offset(&self) -> u32 {
+ self.offset + self.size
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/mod.rs b/vendor/windows-bindgen/src/winmd/writer/mod.rs
new file mode 100644
index 000000000..af49ecfeb
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/mod.rs
@@ -0,0 +1,329 @@
+mod blobs;
+mod codes;
+mod file;
+mod strings;
+mod tables;
+mod traits;
+mod r#type;
+
+use super::*;
+use blobs::Blobs;
+pub use codes::*;
+use metadata::imp::*;
+pub use r#type::*;
+use std::collections::HashMap;
+use strings::Strings;
+pub use tables::*;
+use traits::*;
+
+pub struct Writer {
+ pub blobs: Blobs,
+ pub strings: Strings,
+ pub tables: Tables,
+ pub scopes: HashMap<String, u32>,
+ // TODO: is this faster than jsut using a single HashMap with a (String,String) key?
+ pub type_refs: HashMap<String, HashMap<String, u32>>,
+ pub type_specs: HashMap<Type, u32>,
+}
+
+impl Writer {
+ pub fn new(name: &str) -> Self {
+ let mut writer = Self {
+ blobs: Default::default(),
+ strings: Default::default(),
+ tables: Default::default(),
+ scopes: Default::default(),
+ type_refs: Default::default(),
+ type_specs: Default::default(),
+ };
+
+ writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert("<Module>"), ..Default::default() });
+
+ let name = name.rsplit_once(&['/', '\\']).map_or(name, |(_, name)| name);
+
+ writer.tables.Module.push(Module { Name: writer.strings.insert(name), Mvid: 1, ..Default::default() });
+
+ let name = name.rsplit_once('.').map_or(name, |(_, name)| name);
+
+ writer.tables.Assembly.push(Assembly {
+ Name: writer.strings.insert(name),
+ HashAlgId: 0x00008004,
+ MajorVersion: 0xFF,
+ MinorVersion: 0xFF,
+ BuildNumber: 0xFF,
+ RevisionNumber: 0xFF,
+ Flags: metadata::AssemblyFlags::WindowsRuntime.0,
+ ..Default::default()
+ });
+
+ // Some winmd parsers will fail to read without an `mscorlib` reference. The `insert_module_types` function will typically include it
+ // automatically but a minimal `Module` tree may not add this dependency.
+ writer.insert_scope("System");
+
+ writer
+ }
+
+ pub fn into_stream(self) -> Vec<u8> {
+ file::write(self.tables.into_stream(), self.strings.into_stream(), self.blobs.into_stream())
+ }
+
+ pub fn insert_method_sig(&mut self, call_flags: metadata::MethodCallAttributes, return_type: &Type, param_types: &[Type]) -> u32 {
+ let mut blob = vec![call_flags.0];
+ usize_blob(param_types.len(), &mut blob);
+ self.type_blob(return_type, &mut blob);
+
+ for ty in param_types {
+ self.type_blob(ty, &mut blob);
+ }
+
+ self.blobs.insert(&blob)
+ }
+
+ pub fn insert_field_sig(&mut self, ty: &Type) -> u32 {
+ // TODO: can either cache in Writer, like we do for scopes and type_refs, or regenerate each time.
+ // Profile once we can stress test this with field/method signatures.
+
+ let mut blob = vec![0x6]; // FIELD
+ self.type_blob(ty, &mut blob);
+
+ self.blobs.insert(&blob)
+ }
+
+ fn insert_scope(&mut self, namespace: &str) -> u32 {
+ if let Some(scope) = self.scopes.get(namespace) {
+ *scope
+ } else if namespace == "System" {
+ let scope = ResolutionScope::AssemblyRef(self.tables.AssemblyRef.push2(AssemblyRef {
+ Name: self.strings.insert("mscorlib"),
+ MajorVersion: 4,
+ PublicKeyOrToken: self.blobs.insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this
+ ..Default::default()
+ }))
+ .encode();
+ self.scopes.insert(namespace.to_string(), scope);
+ scope
+ } else {
+ // TODO: may need to capture the original assembly info for external type_refs.
+ let scope = ResolutionScope::AssemblyRef(self.tables.AssemblyRef.push2(AssemblyRef {
+ Name: self.strings.insert(namespace),
+ MajorVersion: 0xFF,
+ MinorVersion: 0xFF,
+ BuildNumber: 0xFF,
+ RevisionNumber: 0xFF,
+ Flags: metadata::AssemblyFlags::WindowsRuntime.0,
+ ..Default::default()
+ }))
+ .encode();
+ self.scopes.insert(namespace.to_string(), scope);
+ scope
+ }
+ }
+
+ pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> u32 {
+ if let Some(key) = self.type_refs.get(namespace) {
+ if let Some(reference) = key.get(name) {
+ return *reference;
+ }
+ }
+
+ let scope = self.insert_scope(namespace);
+
+ let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { TypeName: self.strings.insert(name), TypeNamespace: self.strings.insert(namespace), ResolutionScope: scope })).encode();
+ self.type_refs.entry(namespace.to_string()).or_default().insert(name.to_string(), reference);
+ reference
+ }
+
+ pub fn insert_type_spec(&mut self, ty: Type) -> u32 {
+ if let Some(key) = self.type_specs.get(&ty) {
+ return *key;
+ }
+
+ let mut blob = vec![];
+ self.type_blob(&ty, &mut blob);
+ let signature = self.blobs.insert(&blob);
+
+ let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { Signature: signature })).encode();
+
+ self.type_specs.insert(ty, reference);
+ reference
+ }
+
+ fn type_blob(&mut self, ty: &Type, blob: &mut Vec<u8>) {
+ match ty {
+ Type::Void => blob.push(ELEMENT_TYPE_VOID),
+ Type::Bool => blob.push(ELEMENT_TYPE_BOOLEAN),
+ Type::Char => blob.push(ELEMENT_TYPE_CHAR),
+ Type::I8 => blob.push(ELEMENT_TYPE_I1),
+ Type::U8 => blob.push(ELEMENT_TYPE_U1),
+ Type::I16 => blob.push(ELEMENT_TYPE_I2),
+ Type::U16 => blob.push(ELEMENT_TYPE_U2),
+ Type::I32 => blob.push(ELEMENT_TYPE_I4),
+ Type::U32 => blob.push(ELEMENT_TYPE_U4),
+ Type::I64 => blob.push(ELEMENT_TYPE_I8),
+ Type::U64 => blob.push(ELEMENT_TYPE_U8),
+ Type::F32 => blob.push(ELEMENT_TYPE_R4),
+ Type::F64 => blob.push(ELEMENT_TYPE_R8),
+ Type::ISize => blob.push(ELEMENT_TYPE_I),
+ Type::USize => blob.push(ELEMENT_TYPE_U),
+ Type::String => blob.push(ELEMENT_TYPE_STRING),
+ Type::IInspectable => blob.push(ELEMENT_TYPE_OBJECT),
+ Type::GUID => {
+ let code = self.insert_type_ref("System", "Guid");
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+ }
+ Type::HRESULT => {
+ let code = self.insert_type_ref("Windows.Foundation", "HResult");
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+ }
+ Type::TypeRef(ty) => {
+ if !ty.generics.is_empty() {
+ blob.push(ELEMENT_TYPE_GENERICINST);
+ }
+ let code = self.insert_type_ref(&ty.namespace, &ty.name);
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+
+ if !ty.generics.is_empty() {
+ usize_blob(ty.generics.len(), blob);
+
+ for ty in &ty.generics {
+ self.type_blob(ty, blob);
+ }
+ }
+ }
+ Type::BSTR => {
+ let code = self.insert_type_ref("Windows.Win32.Foundation", "BSTR");
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+ }
+ Type::IUnknown => {
+ let code = self.insert_type_ref("Windows.Win32.Foundation", "IUnknown");
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+ }
+ Type::PCWSTR | Type::PWSTR => {
+ let code = self.insert_type_ref("Windows.Win32.Foundation", "PWSTR");
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+ }
+ Type::PCSTR | Type::PSTR => {
+ let code = self.insert_type_ref("Windows.Win32.Foundation", "PSTR");
+ blob.push(ELEMENT_TYPE_VALUETYPE);
+ usize_blob(code as usize, blob);
+ }
+ Type::ConstRef(ty) => {
+ usize_blob(ELEMENT_TYPE_CMOD_OPT as usize, blob);
+ usize_blob(self.insert_type_ref("System.Runtime.CompilerServices", "IsConst") as usize, blob);
+ usize_blob(ELEMENT_TYPE_BYREF as usize, blob);
+ self.type_blob(ty, blob);
+ }
+ Type::WinrtArrayRef(ty) => {
+ usize_blob(ELEMENT_TYPE_BYREF as usize, blob);
+ usize_blob(ELEMENT_TYPE_SZARRAY as usize, blob);
+ self.type_blob(ty, blob);
+ }
+ Type::WinrtArray(ty) => {
+ usize_blob(ELEMENT_TYPE_SZARRAY as usize, blob);
+ self.type_blob(ty, blob);
+ }
+ Type::Win32Array(ty, bounds) => {
+ usize_blob(ELEMENT_TYPE_ARRAY as usize, blob);
+ self.type_blob(ty, blob);
+ usize_blob(1, blob); // rank
+ usize_blob(1, blob); // count
+ usize_blob(*bounds, blob);
+ }
+ Type::TypeName => {
+ let code = self.insert_type_ref("System", "Type");
+ blob.push(ELEMENT_TYPE_CLASS);
+ usize_blob(code as usize, blob);
+ }
+ Type::MutPtr(ty, pointers) | Type::ConstPtr(ty, pointers) => {
+ for _ in 0..*pointers {
+ usize_blob(ELEMENT_TYPE_PTR as usize, blob);
+ }
+ self.type_blob(ty, blob);
+ }
+ Type::GenericParam(index) => {
+ blob.push(ELEMENT_TYPE_VAR);
+ usize_blob(*index as usize, blob);
+ }
+ }
+ }
+}
+
+fn round(size: usize, round: usize) -> usize {
+ let round = round - 1;
+ (size + round) & !round
+}
+
+fn usize_blob(value: usize, blob: &mut Vec<u8>) {
+ // See II.23.2 in ECMA-335
+ assert!(value < 0x20000000);
+
+ if value < 0x80 {
+ blob.push(value as u8);
+ } else if value < 0x4000 {
+ blob.push((0x80 | (value & 0x3F00) >> 8) as u8);
+ blob.push((value & 0xFF) as u8);
+ } else {
+ blob.push((0xC0 | (value & 0x1F000000) >> 24) as u8);
+ blob.push(((value & 0xFF0000) >> 16) as u8);
+ blob.push(((value & 0xFF00) >> 8) as u8);
+ blob.push((value & 0xFF) as u8);
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_usize_blob() {
+ let mut blob = vec![];
+ usize_blob(0, &mut blob);
+ usize_blob(1, &mut blob);
+ usize_blob(2, &mut blob);
+
+ usize_blob(0x80 - 2, &mut blob);
+ usize_blob(0x80 - 1, &mut blob);
+ usize_blob(0x80, &mut blob);
+ usize_blob(0x80 + 1, &mut blob);
+ usize_blob(0x80 + 2, &mut blob);
+
+ usize_blob(0x4000 - 2, &mut blob);
+ usize_blob(0x4000 - 1, &mut blob);
+ usize_blob(0x4000, &mut blob);
+ usize_blob(0x4000 + 1, &mut blob);
+ usize_blob(0x4000 + 2, &mut blob);
+
+ usize_blob(0x20000000 - 3, &mut blob);
+ usize_blob(0x20000000 - 2, &mut blob);
+ usize_blob(0x20000000 - 1, &mut blob);
+
+ let mut blob = metadata::Blob::new(0, &blob);
+ assert_eq!(blob.read_usize(), 0);
+ assert_eq!(blob.read_usize(), 1);
+ assert_eq!(blob.read_usize(), 2);
+
+ assert_eq!(blob.read_usize(), 0x80 - 2);
+ assert_eq!(blob.read_usize(), 0x80 - 1);
+ assert_eq!(blob.read_usize(), 0x80);
+ assert_eq!(blob.read_usize(), 0x80 + 1);
+ assert_eq!(blob.read_usize(), 0x80 + 2);
+
+ assert_eq!(blob.read_usize(), 0x4000 - 2);
+ assert_eq!(blob.read_usize(), 0x4000 - 1);
+ assert_eq!(blob.read_usize(), 0x4000);
+ assert_eq!(blob.read_usize(), 0x4000 + 1);
+ assert_eq!(blob.read_usize(), 0x4000 + 2);
+
+ assert_eq!(blob.read_usize(), 0x20000000 - 3);
+ assert_eq!(blob.read_usize(), 0x20000000 - 2);
+ assert_eq!(blob.read_usize(), 0x20000000 - 1);
+
+ assert_eq!(blob.slice.len(), 0);
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/strings.rs b/vendor/windows-bindgen/src/winmd/writer/strings.rs
new file mode 100644
index 000000000..1eeae6d43
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/strings.rs
@@ -0,0 +1,35 @@
+use super::*;
+use std::collections::hash_map::*;
+
+pub struct Strings {
+ map: HashMap<String, u32>,
+ stream: Vec<u8>,
+}
+
+impl Default for Strings {
+ fn default() -> Self {
+ Self { map: Default::default(), stream: vec![0] }
+ }
+}
+
+impl Strings {
+ pub fn insert(&mut self, value: &str) -> u32 {
+ if value.is_empty() {
+ return 0;
+ }
+
+ match self.map.entry(value.to_string()) {
+ Entry::Vacant(entry) => {
+ let offset = *entry.insert(self.stream.len() as u32);
+ self.stream.extend_from_slice(value.as_bytes());
+ self.stream.push(0);
+ offset
+ }
+ Entry::Occupied(entry) => *entry.get(),
+ }
+ }
+
+ pub fn into_stream(self) -> Vec<u8> {
+ self.stream.into_stream()
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/tables.rs b/vendor/windows-bindgen/src/winmd/writer/tables.rs
new file mode 100644
index 000000000..4d4b8e354
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/tables.rs
@@ -0,0 +1,361 @@
+#![allow(non_snake_case)]
+
+use super::Write;
+use super::*;
+use metadata::imp::coded_index_size;
+
+#[derive(Default)]
+pub struct Tables {
+ // TODO: use BTreeSet for tables that have a primary key, unless they are naturally sorted.
+ pub Assembly: Vec<Assembly>,
+ pub AssemblyRef: Vec<AssemblyRef>,
+ pub ClassLayout: Vec<ClassLayout>,
+ pub Constant: Vec<Constant>,
+ pub CustomAttribute: Vec<CustomAttribute>,
+ pub Field: Vec<Field>,
+ pub GenericParam: Vec<GenericParam>,
+ pub ImplMap: Vec<ImplMap>,
+ pub InterfaceImpl: Vec<InterfaceImpl>,
+ pub MemberRef: Vec<MemberRef>,
+ pub MethodDef: Vec<MethodDef>,
+ pub Module: Vec<Module>,
+ pub ModuleRef: Vec<ModuleRef>,
+ pub NestedClass: Vec<NestedClass>,
+ pub Param: Vec<Param>,
+ pub Property: Vec<Property>,
+ pub TypeDef: Vec<TypeDef>,
+ pub TypeRef: Vec<TypeRef>,
+ pub TypeSpec: Vec<TypeSpec>,
+}
+
+#[derive(Default)]
+pub struct Assembly {
+ pub HashAlgId: u32,
+ pub MajorVersion: u16,
+ pub MinorVersion: u16,
+ pub BuildNumber: u16,
+ pub RevisionNumber: u16,
+ pub Flags: u32,
+ pub PublicKey: u32,
+ pub Name: u32,
+ pub Culture: u32,
+}
+
+#[derive(Default)]
+pub struct AssemblyRef {
+ pub MajorVersion: u16,
+ pub MinorVersion: u16,
+ pub BuildNumber: u16,
+ pub RevisionNumber: u16,
+ pub Flags: u32,
+ pub PublicKeyOrToken: u32,
+ pub Name: u32,
+ pub Culture: u32,
+ pub HashValue: u32,
+}
+
+#[derive(Default)]
+pub struct ClassLayout {
+ pub PackingSize: u16,
+ pub ClassSize: u32,
+ pub Parent: u32,
+}
+
+#[derive(Default)]
+pub struct Constant {
+ pub Type: u16,
+ pub Parent: u32,
+ pub Value: u32,
+}
+
+#[derive(Default)]
+pub struct CustomAttribute {
+ pub Parent: u32,
+ pub Type: u32,
+ pub Value: u32,
+}
+
+#[derive(Default)]
+pub struct Field {
+ pub Flags: u16,
+ pub Name: u32,
+ pub Signature: u32,
+}
+
+#[derive(Default)]
+pub struct GenericParam {
+ pub Number: u16,
+ pub Flags: u16,
+ pub Owner: u32,
+ pub Name: u32,
+}
+
+#[derive(Default)]
+pub struct ImplMap {
+ pub MappingFlags: u16,
+ pub MemberForwarded: u32,
+ pub ImportName: u32,
+ pub ImportScope: u32,
+}
+
+#[derive(Default)]
+pub struct InterfaceImpl {
+ pub Class: u32,
+ pub Interface: u32,
+}
+
+#[derive(Default)]
+pub struct MemberRef {
+ pub Class: u32,
+ pub Name: u32,
+ pub Signature: u32,
+}
+
+#[derive(Default)]
+pub struct MethodDef {
+ pub RVA: u32,
+ pub ImplFlags: u16,
+ pub Flags: u16,
+ pub Name: u32,
+ pub Signature: u32,
+ pub ParamList: u32,
+}
+
+#[derive(Default)]
+pub struct Module {
+ pub Generation: u16,
+ pub Name: u32,
+ pub Mvid: u32,
+ pub EncId: u32,
+ pub EncBaseId: u32,
+}
+
+#[derive(Default)]
+pub struct ModuleRef {
+ pub Name: u32,
+}
+
+#[derive(Default)]
+pub struct NestedClass {
+ pub NestedClass: u32,
+ pub EnclosingClass: u32,
+}
+
+#[derive(Default)]
+pub struct Param {
+ pub Flags: u16,
+ pub Sequence: u16,
+ pub Name: u32,
+}
+
+#[derive(Default)]
+pub struct Property {
+ pub Flags: u16,
+ pub Name: u32,
+ pub Type: u32,
+}
+
+#[derive(Default)]
+pub struct TypeDef {
+ pub Flags: u32,
+ pub TypeName: u32,
+ pub TypeNamespace: u32,
+ pub Extends: u32,
+ pub FieldList: u32,
+ pub MethodList: u32,
+}
+
+#[derive(Default)]
+pub struct TypeRef {
+ pub ResolutionScope: u32,
+ pub TypeName: u32,
+ pub TypeNamespace: u32,
+}
+
+#[derive(Default)]
+pub struct TypeSpec {
+ pub Signature: u32,
+}
+
+impl Tables {
+ pub fn into_stream(self) -> Vec<u8> {
+ if [self.AssemblyRef.len(), self.ClassLayout.len(), self.Constant.len(), self.CustomAttribute.len(), self.Field.len(), self.GenericParam.len(), self.ImplMap.len(), self.InterfaceImpl.len(), self.MemberRef.len(), self.MethodDef.len(), self.Module.len(), self.ModuleRef.len(), self.NestedClass.len(), self.Param.len(), self.Property.len(), self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()].iter().any(|len| *len > u32::MAX as usize) {
+ panic!("metadata table too large");
+ }
+
+ let resolution_scope = coded_index_size(&[self.Module.len(), self.ModuleRef.len(), self.AssemblyRef.len(), self.TypeRef.len()]);
+
+ let type_def_or_ref = coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]);
+
+ let has_constant = coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]);
+
+ let type_or_method_def = coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]);
+
+ let valid_tables: u64 = 1 << 0 | // Module
+ 1 << 0x01 | // TypeRef
+ 1 << 0x02 | // TypeDef
+ 1 << 0x04 | // Field
+ 1 << 0x06 | // MethodDef
+ 1 << 0x08 | // Param
+ 1 << 0x09 | // InterfaceImpl
+ 1 << 0x0A | // MemberRef
+ 1 << 0x0B | // Constant
+ 1 << 0x0C | // CustomAttribute
+ 1 << 0x0F | // ClassLayout
+ 1 << 0x17 | // Property
+ 1 << 0x1A | // ModuleRef
+ 1 << 0x1B | // TypeSpec
+ 1 << 0x1C | // ImplMap
+ 1 << 0x20 | // Assembly
+ 1 << 0x23 | // AssemblyRef
+ 1 << 0x29 | // NestedClass
+ 1 << 0x2A; // GenericParam
+
+ // The table stream header...
+
+ let mut buffer = Vec::new();
+ buffer.write_u32(0); // Reserved
+ buffer.write_u8(2); // MajorVersion
+ buffer.write_u8(0); // MinorVersion
+ buffer.write_u8(0b111); // HeapSizes
+ buffer.write_u8(0); // Reserved
+ buffer.write_u64(valid_tables);
+ buffer.write_u64(0); // Sorted
+
+ // Followed by the length of each of the valid tables...
+
+ buffer.write_u32(self.Module.len() as u32);
+ buffer.write_u32(self.TypeRef.len() as u32);
+ buffer.write_u32(self.TypeDef.len() as u32);
+ buffer.write_u32(self.Field.len() as u32);
+ buffer.write_u32(self.MethodDef.len() as u32);
+ buffer.write_u32(self.Param.len() as u32);
+ buffer.write_u32(self.InterfaceImpl.len() as u32);
+ buffer.write_u32(self.MemberRef.len() as u32);
+ buffer.write_u32(self.Constant.len() as u32);
+ buffer.write_u32(self.CustomAttribute.len() as u32);
+ buffer.write_u32(self.ClassLayout.len() as u32);
+ buffer.write_u32(self.Property.len() as u32);
+ buffer.write_u32(self.ModuleRef.len() as u32);
+ buffer.write_u32(self.TypeSpec.len() as u32);
+ buffer.write_u32(self.ImplMap.len() as u32);
+ buffer.write_u32(self.Assembly.len() as u32);
+ buffer.write_u32(self.AssemblyRef.len() as u32);
+ buffer.write_u32(self.NestedClass.len() as u32);
+ buffer.write_u32(self.GenericParam.len() as u32);
+
+ // Followed by each table's rows...
+
+ for x in self.Module {
+ buffer.write_u16(x.Generation);
+ buffer.write_u32(x.Name);
+ buffer.write_u32(x.Mvid);
+ buffer.write_u32(x.EncId);
+ buffer.write_u32(x.EncBaseId);
+ }
+
+ for x in self.TypeRef {
+ buffer.write_code(x.ResolutionScope, resolution_scope);
+ buffer.write_u32(x.TypeName);
+ buffer.write_u32(x.TypeNamespace);
+ }
+
+ for x in &self.TypeDef {
+ buffer.write_u32(x.Flags);
+ buffer.write_u32(x.TypeName);
+ buffer.write_u32(x.TypeNamespace);
+ buffer.write_code(x.Extends, type_def_or_ref);
+ buffer.write_index(x.FieldList, self.Field.len());
+ buffer.write_index(x.MethodList, self.MethodDef.len());
+ }
+
+ for x in self.Field {
+ buffer.write_u16(x.Flags);
+ buffer.write_u32(x.Name);
+ buffer.write_u32(x.Signature);
+ }
+
+ for x in self.MethodDef {
+ buffer.write_u32(x.RVA);
+ buffer.write_u16(x.ImplFlags);
+ buffer.write_u16(x.Flags);
+ buffer.write_u32(x.Name);
+ buffer.write_u32(x.Signature);
+ buffer.write_index(x.ParamList, self.Param.len());
+ }
+
+ for x in self.Param {
+ buffer.write_u16(x.Flags);
+ buffer.write_u16(x.Sequence);
+ buffer.write_u32(x.Name);
+ }
+
+ for x in self.InterfaceImpl {
+ buffer.write_index(x.Class, self.TypeDef.len());
+ buffer.write_code(x.Interface, type_def_or_ref);
+ }
+
+ for x in self.Constant {
+ buffer.write_u16(x.Type);
+ buffer.write_code(x.Parent, has_constant);
+ buffer.write_u32(x.Value);
+ }
+
+ for x in self.TypeSpec {
+ buffer.write_u32(x.Signature);
+ }
+
+ for x in self.Assembly {
+ buffer.write_u32(x.HashAlgId);
+ buffer.write_u16(x.MajorVersion);
+ buffer.write_u16(x.MinorVersion);
+ buffer.write_u16(x.BuildNumber);
+ buffer.write_u16(x.RevisionNumber);
+ buffer.write_u32(x.Flags);
+ buffer.write_u32(x.PublicKey);
+ buffer.write_u32(x.Name);
+ buffer.write_u32(x.Culture);
+ }
+
+ for x in self.AssemblyRef {
+ buffer.write_u16(x.MajorVersion);
+ buffer.write_u16(x.MinorVersion);
+ buffer.write_u16(x.BuildNumber);
+ buffer.write_u16(x.RevisionNumber);
+ buffer.write_u32(x.Flags);
+ buffer.write_u32(x.PublicKeyOrToken);
+ buffer.write_u32(x.Name);
+ buffer.write_u32(x.Culture);
+ buffer.write_u32(x.HashValue);
+ }
+
+ for x in self.GenericParam {
+ buffer.write_u16(x.Number);
+ buffer.write_u16(x.Flags);
+ buffer.write_code(x.Owner, type_or_method_def);
+ buffer.write_u32(x.Name);
+ }
+
+ // TODO: sort GenericParam table prior to writing. This needs to be done for all tables with a primary index. See II.22
+
+ // TODO: do these get naturally sorted by virtue of how they're pushed into "tables" in type def order?
+
+ // Table Primary Key Column
+ // ClassLayout Parent
+ // Constant Parent
+ // CustomAttribute Parent
+ // DeclSecurity Parent
+ // FieldLayout Field
+ // FieldMarshal Parent
+ // FieldRVA Field
+ // GenericParam Owner
+ // GenericParamConstraint Owner
+ // ImplMap MemberForwarded
+ // InterfaceImpl Class
+ // MethodImpl Class
+ // MethodSemantics Association
+ // NestedClass NestedClass
+
+ buffer.into_stream()
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/traits.rs b/vendor/windows-bindgen/src/winmd/writer/traits.rs
new file mode 100644
index 000000000..45304899a
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/traits.rs
@@ -0,0 +1,66 @@
+use super::*;
+
+pub trait Write {
+ unsafe fn write_header<T: Sized>(&mut self, value: &T);
+ fn write_u8(&mut self, value: u8);
+ fn write_u16(&mut self, value: u16);
+ fn write_u32(&mut self, value: u32);
+ fn write_u64(&mut self, value: u64);
+ fn write_code(&mut self, value: u32, size: usize);
+ fn write_index(&mut self, index: u32, len: usize);
+ fn into_stream(self) -> Self;
+}
+
+impl Write for Vec<u8> {
+ unsafe fn write_header<T: Sized>(&mut self, value: &T) {
+ self.extend_from_slice(std::slice::from_raw_parts(value as *const _ as _, std::mem::size_of::<T>()));
+ }
+
+ fn write_u8(&mut self, value: u8) {
+ self.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_u16(&mut self, value: u16) {
+ self.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_u32(&mut self, value: u32) {
+ self.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_u64(&mut self, value: u64) {
+ self.extend_from_slice(&value.to_le_bytes());
+ }
+
+ fn write_code(&mut self, value: u32, size: usize) {
+ if size == 2 {
+ self.write_u16(value as u16);
+ } else {
+ self.write_u32(value);
+ }
+ }
+
+ fn write_index(&mut self, index: u32, len: usize) {
+ if len < (1 << 16) {
+ self.write_u16(index as u16 + 1);
+ } else {
+ self.write_u32(index + 1);
+ }
+ }
+
+ fn into_stream(mut self) -> Self {
+ self.resize(round(self.len(), 4), 0);
+ self
+ }
+}
+
+pub trait Push2<T> {
+ fn push2(&mut self, value: T) -> u32;
+}
+
+impl<T> Push2<T> for Vec<T> {
+ fn push2(&mut self, value: T) -> u32 {
+ self.push(value);
+ (self.len() - 1) as u32
+ }
+}
diff --git a/vendor/windows-bindgen/src/winmd/writer/type.rs b/vendor/windows-bindgen/src/winmd/writer/type.rs
new file mode 100644
index 000000000..3f0178654
--- /dev/null
+++ b/vendor/windows-bindgen/src/winmd/writer/type.rs
@@ -0,0 +1,80 @@
+#![allow(dead_code, clippy::upper_case_acronyms)]
+
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct TypeName {
+ pub namespace: String,
+ pub name: String,
+ pub generics: Vec<Type>,
+}
+
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+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,
+ TypeRef(TypeName),
+ GenericParam(u16),
+ MutPtr(Box<Self>, usize),
+ ConstPtr(Box<Self>, usize),
+ Win32Array(Box<Self>, usize),
+ WinrtArray(Box<Self>),
+ WinrtArrayRef(Box<Self>),
+ ConstRef(Box<Self>),
+}
+
+impl Type {
+ pub fn into_mut_ptr(self) -> Self {
+ match self {
+ Self::MutPtr(ty, count) => Self::MutPtr(ty, count + 1),
+ Self::ConstPtr(ty, count) => Self::MutPtr(ty, count + 1),
+ _ => Self::MutPtr(Box::new(self), 1),
+ }
+ }
+
+ pub fn into_const_ptr(self) -> Self {
+ match self {
+ Self::MutPtr(ty, count) => Self::ConstPtr(ty, count + 1),
+ Self::ConstPtr(ty, count) => Self::ConstPtr(ty, count + 1),
+ _ => Self::ConstPtr(Box::new(self), 1),
+ }
+ }
+
+ pub fn into_array(self, len: usize) -> Self {
+ Self::Win32Array(Box::new(self), len)
+ }
+}
+
+pub struct Signature {
+ pub params: Vec<SignatureParam>,
+ pub return_type: Type,
+ pub call_flags: u8,
+}
+
+// TODO: just Param?
+pub struct SignatureParam {
+ pub name: String,
+ pub ty: Type,
+}